Skip to content

UltiTools-API 6.3.0 更新说明 ​

6.3.0 整合了框架的命令、配置、事务、模块生命周期和面板集成。 本说明以已发布的 v6.2.5 内容为比较基准,而不是提交之间的祖先关系。 模块 EventBus 和声明式 GUI 在 6.2.5 中已经存在; 下文介绍的是对它们的修复和扩展,并非首次引入。

升级前准备 ​

  • 备份服务器配置和模块数据。使用 JSON 存储时,将 .ultitools-journal 与数据表一起备份;不要删除该日志目录,每个数据目录只允许一个服务器使用。
  • 安装针对 UltiTools-API 6.3.0 编译的模块构建,并在模块 plugin.yml 中声明 api-version: 630。如果服务器依赖模块,请继续使用 6.2.5,直到所用的每个模块都发布了 6.3.0 构建。只升级框架会导致旧模块无法加载。
  • 停服后替换框架和受影响模块的 JAR,再重启服务器。 /ul reload 只重载配置,不会重载 JAR。
  • 框架支持 Paper 1.19.2 build 163 或更新版本,不支持普通 Spigot。 Paper 1.20.5 之前使用 Java 17,从 Paper 1.20.5 起使用 Java 21。Java 8 字节码不代表承诺支持 Java 8 服务器运行时。
  • UltiKits、UltiLogin、UltiMail、UltiRemoteBag 和 UltiTrade 要求 Paper 1.21 或更新版本; 在框架支持的较旧服务器上,它们的物品栏界面可能失败(见已知问题)。

模块目录可用性 ​

6.3.0 发布时,/upm 目录尚未提供 6.3.0(api-version: 630)模块构建, 6.3.0 也会在启动时拒绝为 6.2.x 构建的模块。如果服务器依赖模块, 请继续使用 6.2.5,等所用的每个模块都有 6.3.0 构建后再升级。

不兼容的 API 变更与迁移 ​

使用 6.3.0 重新编译下游模块,并将依赖保持为 provided(Maven)或 compileOnly(Gradle)。完整契约和替代方案见升级检查清单、 移除登记表和 逐项变更记录。 主要变更如下:

  • 移除了 AbstractCommandExecutor 及其拼写错误的兼容类 AbstractCommendExecutor。 请继承 abstracts.command.BaseCommandExecutor 并实现 handleHelp(CommandSender)。
  • UltiToolsPlugin.unregisterSelf() 和 reloadSelf() 现在为 final。将覆写逻辑移至 onUnregister() 和 onReload(),并移除对旧父类生命周期方法的调用。 覆写任一 final 方法的旧主类会因 IncompatibleClassChangeError 被拒绝加载; 硬依赖该模块的模块也会被拒绝加载。
  • 移除的类型包括 AbstractDataEntity(改用 BaseDataEntity<ID>)、PagingPage(改用 BasePaginationPage)、OkCancelPage(改用 BaseConfirmationPage)、VersionWrapper 和 DefaultVersionWrapper(改用 XVersionUtils)。
  • 移除的注册 API 包括六参数的 UltiToolsPlugin 构造器、旧的 七参数 PluginManager.register(...)、按包注册命令或监听器的 重载,以及 ListenerManager.register(UltiToolsPlugin, Listener)。请使用登记表中列出的现行构造器 及基于类或模块的注册 API。
  • 移除了 TempListener.player(...) 和 PlayerTempListener;改用带过滤条件的 TempListener.common(...)。 无实际作用的 @OptionalParam 注解已移除,没有替代项。
  • 移除了旧 CGLIB 工厂和代理创建 API;代理现在通过 AopProxyResolver 使用 ByteBuddy 构建。 移除了 Propagation.NESTED。
  • 移除了 UltiTools#getEconomy();改用 EconomyUtils.getEconomy() 或其包装方法。 已归档的 Adventure audience provider 也已移除;请使用 Paper 原生 Adventure audiences。
  • 移除了 AbstractConfigEntity#getConfig()。检查键是否存在时使用 isPresentInFile(...), 读取值时使用声明的字段,保存时使用下文列出的显式保存 API。
  • 移除了声明式 GUI 中无实际作用的 builder 方法对 Container.background/getBackground 和 GridView.rows/getMaxRows。GuiRenderer.initialize 现在接受 Supplier<Widget>。
  • 移除了按查看者控制日志流的 start/stop/pause/resume API, 不再在缺少浏览器身份的情况下假装控制投递;这些远程操作会被拒绝。

旧 JAR 的结果并不能统一归为两类:父类不可用的类可能在扫描时被跳过, 覆写新设为 final 的生命周期方法可能导致整个模块被拒绝加载, 调用已移除方法的旧代码则可能直到实际执行时才以 NoSuchMethodError 失败。 请查阅具体符号的变更记录,不要将启动成功视为兼容性证明。

配置与语言文件 ​

  • 不会自动修复或覆盖服主编写的配置。无效值会被报告并拒绝使用 (在已说明的情形下使用声明的默认值作为内存值),不会将默认值写回文件。 不支持或无效的约束可能导致受影响模块或重载被拒绝。
  • 配置写入会声明自己负责的键;如果无法保留无关字节,或文件在读取后发生变化, 则拒绝写入。请阅读警告,修正指出的布局问题,或在外部编辑后先重载,再重试。 支持的 YAML 布局、原子写入的回退方式和恢复限制见 COMPATIBILITY.md 的配置章节。
  • save() 只持久化模块自身的更改。服主命令使用 saveOperatorChange(...) 或 saveOperatorMapEntry(...) 保存指定的更改;模块管理的文件使用 OperatorFiles。 关闭、卸载或替换时都不会自动保存配置。
  • ConfigConverter<T> 与 @ConfigConverterFor 是新的转换扩展点。 旧解析器在 6.3.0 中仍为弃用状态,计划于 6.4.0 移除。 对于尚不支持的声明字段类型,请在配置初始化之前注册转换器。
  • 绑定配置的 @Scheduled 和 @CmdCD 支持实时配置值。请声明 api-version: 630,保持绑定的定时方法同步执行,并移除绑定字段上 多余的 @Range;可接受的范围由绑定定义。
  • 要将文本值留空,请写 key: '';删除键会在下次启动时请求使用默认值。
  • 官方语言文件由框架管理,升级时可能被替换,同时保留备份并记录日志。 如需自定义文本,请复制语言文件并使用新名称,再选择该副本; 自定义文件仍由服主管理。框架消息遵循所选的 language。

事务、持久化与依赖注入 ​

  • @Transactional 已通过 AOP 路径接入 MySQL、SQLite 和 JSON。 回滚规则选择匹配深度最浅的异常类型;REQUIRES_NEW 和 NOT_SUPPORTED 会挂起外层作用域。
  • JSON 事务暂存更改,在一个插件的各张表之间原子发布,并在崩溃后通过日志恢复。 持久性和文件系统相关限制见 JSON 事务。 普通写入和编程式事务读取可能为等待表锁阻塞最多五秒。 在注解式 JSON 事务内进行读后修改再写入时,请使用 updateIf 或 REPEATABLE_READ。
  • 已加入现有事务的 @Transactional 方法抛出按其回滚规则需要回滚的异常, 或嵌套的 DataOperator#transaction(...) 作用域失败时,即使调用者捕获异常, 也会将整个事务标为 rollback-only。最外层提交会回滚并抛出 UnexpectedRollbackException。
  • JSON 读取返回独立副本;修改后使用 update(...) 持久化。 无条件 del() 会被拒绝,而不是删除整张表。访问其他模块的实体操作器也会被拒绝。
  • ByteBuddy 替代了 CGLIB。请通过 ProxyFactory.isProxyClass(...) 检测代理,不要依赖类名。 必需的注入失败或必需的 AOP 契约无法代理时,模块会被拒绝加载。
  • @Service(priority) 用于选择同类型候选(数值较高者优先);最高优先级相同则拒绝。 registerSingleton 会执行注入、生命周期回调和 bean 后处理器。
  • scanBasePackageClasses、组合构造型注解、模块的扫描开关和条件监听器注册均已生效。 依赖缺失或循环依赖会导致受影响模块被拒绝加载; 缺少 name: 的模块 JAR 会被拒绝,不再与其他模块共用存储。
  • 移除了基于名称的类加载过滤器;它们不是沙箱。 模块 JAR 校验保留 100 MB 大小和 10,000 个条目的限制。请只安装你信任的模块。

命令、任务、GUI 与模块生命周期 ​

  • 同步命令现在派发时就在主线程上执行,不再等到下一个 tick。 在物品栏点击处理器中,请使用 runTask 延后物品栏更改和命令派发。 嵌套命令派发立即执行;命令派发自身时,会在同一个 tick 遇到自己的使用锁或冷却, 不受控的递归可能导致栈溢出。异步方法体仍然异步执行。
  • 继承的 @CmdMapping 和 @Scheduled 方法会被识别。@CmdTarget 采用允许缩小范围的覆盖语义; 扩大或横向改变范围的覆写会导致命令类被拒绝。Tab 补全在提供建议或调用建议方法之前检查权限。
  • 冷却以执行器实例为作用域;@UsageLimit 在派发被拒绝和执行完成时都会释放已取得的锁。 ContainConsole() 现在默认为 true。 @AsyncCommand.timeout() 会停止等待并报告超时;方法体可能继续在后台运行。
  • 声明式 GUI 的状态变化现在会触发重绘,网格布局支持通用组件类型, 玩家自身物品栏中的点击不再传递给仅面向 GUI 的处理器。
  • 卸载和重载生命周期钩子会保留框架清理逻辑;getPluginList() 返回不可修改的快照。 模块替换会在重启时观察加载结果,然后才提交更新; 加载失败时可以恢复保留的旧 JAR。
  • @PlayerCache 保存失败不会中断玩家退出时的其他清理。缓存条目仍会被移除, 框架不会重试保存;需要更强保证的模块必须自行持久化或重试。

UltiCloud 与远程管理 ​

/panel 链接立即切换为服主认证 ​

创建与服务器关联的 /panel magic-link 立即要求已认证的服务器所有者身份: 没有匿名回退,也没有宽限期。请求链接前,请先通过 /ulticloud login 连接服务器。 这不要求每个打开链接的玩家都拥有该服务器。 普通网站账号登录、浏览器 magic-link 验证和游戏内 /login 命令保持不变。

UltiCloudRequests 使用服务器凭据发送 POST /auth/magic-link 和 GET /auth/magic-link/poll。 轮询时使用 requestId,不要使用玩家 UUID;不再支持仅凭 UUID 轮询。 遇到 NOT_CONNECTED 时不要匿名重试,并在主线程之外调用该辅助类。 认证请求契约说明了辅助 API 和失败处理方式。

其他远程管理变更 ​

  • 八个 ultipanel.capabilities.* 开关控制面板操作。监控、日志、玩家事件和文件读取默认开启; 文件写入、删除、命令执行和服务器属性访问默认关闭。 请只启用服主需要的能力。
  • 远程路径在使用前会被解析,并限制在可编辑的根目录内;递归删除需要显式请求。 删除符号链接只会移除链接,不会删除目标;递归删除不会跟随链接。 受保护文件的别名会被拒绝访问。
  • 命令黑名单可由服主编辑。格式错误的列表会被整体拒绝, 同时记录警告并保留默认值;显式空列表仍然有效。
  • 远程文件操作被拒绝时,会在远程操作日志中记录为 DENIED。 服务器属性编辑和其他文件写入分别使用各自的能力开关。
  • 云登录、登出、令牌刷新和 WebSocket 工作都限定在单个会话内: 已失效的工作不能重新激活已登出的会话。凭据迁移到服务器的 .ultikits 凭据存储。 如果旧存储与格式错误的当前存储同时存在,两者的身份都不会被覆盖; 请先修正当前文档,再重试。
  • 在 Paper 1.20.5 及更新版本上,框架日志流会镜像控制台输出。 在 Paper 1.19.2 至 1.20.4 上无法镜像控制台:启动时会警告,日志流只包含插件日志行。 两种情况都没有修复下表列出的面板浏览器实时连接缺陷。

已知问题与临时处理方式 ​

这些限制计划在 6.4.0 跟进。模块和面板条目属于生态产品的限制, 并不表示本次框架发布修复了这些独立交付的产品。

受影响产品 / 症状临时处理方式跟踪
框架:/upm check 在启动后的最初几秒可能提示没有更新等待控制台输出启动更新检查结果,再重试。#663
框架:要求 Paper 1.21 或更新版本的模块,在较旧 Paper 上可能被误报为针对旧框架构建先检查模块的服务器版本要求,再判断是否为框架构建问题。#658
UltiKits、UltiLogin、UltiMail、UltiRemoteBag 和 UltiTrade 的物品栏界面在较旧 Paper 上可能失败请在 Paper 1.21 或更新版本上运行这五个模块。#655
框架:部分模块重载时,结果会在日志中重复两次,在回复中重复一次读取第一次结果,忽略重复内容。#665
框架:重载或配置提示可能让人误以为需要重启,或混用语言;切换语言后 YAML 锚点注释可能展开修正指出的无效值后运行 /ul reload;被拒绝的面板编辑没有写入任何内容,无需重启。#598
UltiEconomy:扣款和入账之间进程停止,可能导致转账丢失且没有日志记录没有模块层面的临时处理方式;非正常停服后,请核查报告的丢失转账并手动修正余额。#44
UltiEconomy:转账或退款失败的回复可能误导;没有余额行时兑换纸币可能没有回复,并保留纸币数据库出问题后,再次付款前先检查余额和日志。#45
UltiLogin:控制台或面板执行 logadmin reset 可能在日志中暴露新密码在游戏内重置密码,该路径会遮蔽密码日志,并保持日志私密。#57
UltiWorlds:PvP 持久化失败后,运行时标志可能维持已更改状态,直到下一个玩家进入该世界重新执行命令,确认运行时值与保存值一致。#58
面板:插件配置编辑器为空或不可用直接在服务器上编辑配置文件。Tracked internally
面板:设置页在服务器接受前就提示已保存;其中 14 项设置有些并非每个服务器都具备检查服务器的实际设置,不要将成功消息当作确认。Tracked internally
面板:浏览器没有实时推送、没有远程命令输出,管理状态栏即使在线也显示 Disconnected在服务器控制台读取输出,使用仪表盘确认在线状态。Tracked internally
面板:命令被拒绝后仍提示 Command execution request sent检查 ultipanel.capabilities.commands 和服务器控制台;命令默认关闭。Tracked internally
面板:旧付费激活码兑换永久 Pro 不可用或失败没有已验证的自助临时处理方式。符合条件的持有者原有的永久 Pro 权益仍受支持;完整修复延后至 6.4.0,此前兑换可能持续不可用。Tracked internally
开发者 CLI:ultikits versions list 的字段显示为 undefined在面板或目录网页中查询模块版本。Tracked internally

延伸参考 ​

  • COMPATIBILITY.md:迁移检查清单、配置写入规则、支持 矩阵、事务持久性限制和运行时依赖归属。
  • compatibility/records/6.3.0.md:精确的移除项和运行时变更。
  • compatibility/DEPRECATIONS.md:累计生成的登记表。
  • XSeries 不再打包进框架;使用它的模块需自行声明为 provided/compileOnly。Paper 加载框架声明的库,并提供 Gson、 MySQL Connector/J、protobuf 和 slf4j。框架使用 JDK 21 构建,输出 Java 8 字节码; 这并不为 Paper 提供的依赖另行设定运行时最低版本。

贡献者

基于 MIT 许可发布