Linlang 使用 A.B.C.D 四段版本号。API 与 Runtime 不一定需要完全相同,是否允许运行按照以下规则判断:
| 差异 | 处理方式 | ||
|---|---|---|---|
| A 或 B 不同 | 无法初始化 | ||
| A、B 相同,Runtime 的 C 低于插件要求 | 无法初始化,提示 Runtime 可能缺少类或方法 | ||
| A、B 相同,Runtime 的 C 高于插件要求 | 初始化,但打印兼容性警告 | ||
| A、B、C 相同,仅 D 不同 | 初始化 | ||
| 版本缺失或格式无效 | 无法初始化,提示检查构建版本信息。 |
例如,插件依赖 3.0.1.1 时,Runtime 3.0.1.10 可以直接使用,3.0.2.0 会提示警告,3.0.0.10 和 3.1.0.0 则不允许运行。
版本检查只比较版本号的数字部分,-SNAPSHOT、-rc.1 和 +build.1 等构建后缀不参与兼容性和更新判断。
运行时在创建自身服务前检查随构建加载的 API 版本;插件通过 Lin 初始化时,也会在创建 Facade 和执行初始化回调前检查。拒绝时抛出 IllegalStateException,警告不会中断初始化。
版本数字比较必须位于 API:检查的目的正是在调用 Runtime 新接口前判断这些接口是否存在。Runtime 正常启动后,API 会根据检查结果的 Problem 代码查询运行时问题目录,使用当前语言的说明和处理建议组成最终消息。检查规则、异常文本、警告文本和 /linlang problem 因而使用同一组代码与定义。
如果 Runtime 尚未安装、版本早到无法提供当前接口,或审计与语言服务尚未建立,检查会使用 API 内置的简短英文消息。这是启动安全回退,不是另一套兼容规则。
Runtime 的 C 低于插件要求时,运行时无法保证插件引用的新类和新方法存在,因此必须在创建 Facade 前拒绝初始化。提示中会附上 Linlang 项目地址 ⇱,引导管理员安装新构建。仅 D 较低仍然保持静默,因为 D 版本不允许增加公开 API。
如果不希望 Runtime 的 C 高于插件依赖版本时输出兼容性警告,可以在 plugins/LinlangRuntimeBukkit/config.yml 中关闭:
compatibility:
warn-on-compatible-version-difference: false
该设置只隐藏 LIN-RUNTIME-VERSION-MISMATCH 警告,不改变版本比较结果。A、B 不同、Runtime 的 C 低于插件要求或版本格式无效时仍会拒绝初始化。D 差异原本就不会产生兼容性警告。运行时启用完成时显示的 API、Runtime 和 Plugin 版本属于基本启动信息,也不会被此设置隐藏。修改后执行 /linlang reload-all 即可重新应用版本警告策略。
Bukkit 中多个插件共享运行时提供的 API 类。因此,Lin.API_VERSION 表示当前加载的 API 版本,不能用它判断某个插件编译时使用了哪个版本。
使用 Maven 构建时,Lin.init(this)、Lin.setup(this, options) 和 Lin.configure(this, options) 会读取插件 Jar 中的 META-INF/maven/.../pom.xml,找到 me.jling:linlang-api 依赖及其属性值。通常不需要再手写版本参数。
其他构建系统可以在插件 Jar 中提供:
META-INF/linlang/required-api.properties
文件内容为:
version=3.0.0.0
独立版本资源的优先级高于 Maven POM。检测到的值必须符合 A.B.C.D 格式。
无法生成上述构建元数据时,可以显式传入插件依赖的 API 版本:
lin = Lin.setup(this, "3.0.0.0", new LinOptions()
.pluginLogger(true)
.totalLocale("zh_CN"));
这里的 3.0.0.0 是插件编译时依赖的 linlang-api 版本,不是插件自身的版本。不要用 Lin.API_VERSION 替代这个声明。
Lin.init(this, requiredVersion)、Lin.configure(this, requiredVersion, options)、Lin.find(requiredVersion) 和使用回调的 Lin.setup(this, requiredVersion, builder) 都支持相同检查。
如果自动检测失败且没有显式传入版本,初始化会回退到当前加载的 Lin.API_VERSION,此时无法识别插件自身的编译依赖。非 Maven 项目应提供独立版本资源或显式版本。版本检查不会转换不兼容的接口调用;不要通过捕获异常后继续获取服务来绕过检查。
api.linlang.runtime.version.VersionCheck 是不依赖 Runtime 状态、语言文件或网络的纯比较入口:
VersionCheck.Result result = VersionCheck.check(requiredVersion, installedVersion);
boolean allowed = result.allowed();
boolean warning = result.warning();
String message = result.message();
String problemCode = result.code();
check 只返回结果,不输出日志。code() 返回与结果对应的稳定 Problem 代码;完全兼容时返回空字符串。message() 是不依赖 Runtime 的英文回退文本,不代表当前运行时语言。
一般插件不需要自行调用 requireCompatible,Lin.init/setup/configure 已经使用运行时问题目录完成检查和输出。启动器等无法依赖审计服务的早期代码可以调用 requireCompatible(requiredVersion, installedVersion, warningReceiver),并自行提供警告接收器。
后续网络模块取得最新版本字符串后,可以直接调用:
VersionCheck.UpdateResult update = VersionCheck.checkUpdate(
lin.runtimeVersion(), latestVersion);
boolean newer = update.updateAvailable();
boolean compatible = update.compatibility().allowed();
String projectUrl = update.projectUrl();
checkUpdate 将最新版本与本地版本比较。仅 D 增加也会令 updateAvailable() 返回 true,但不产生兼容性警告;跨 A.B 的更新会标记为不兼容,不能直接替换。无效版本会抛出 IllegalArgumentException,网络模块应处理远端数据格式错误。
目前没有自动联网、下载或更新行为。调用此入口不会停止正在运行的服务,也不会自动通知管理员,由调用方决定通知时机。
兼容性问题使用 LIN-RUNTIME-VERSION-INCOMPATIBLE、LIN-RUNTIME-VERSION-MISMATCH 和 LIN-RUNTIME-VERSION-INVALID 三个问题代码。在运行时能够正常启动时,可以通过 /linlang problem <代码> 查询含义。
讨论