多版本兼容
多版本兼容
SnowyGems 支持 1.21.4 及以上的全部版本,包括 1.21.5 ~ 1.21.11 与 26.x。同一份配置可以直接发到不同版本的子服,高版本内容在低版本上自动跳过。
实现原理:不猜版本,只问服务端
大多数插件用「如果版本 ≥ X 就支持 Y」的写法,问题是每出一个新版本都要更新插件,而且 Mojang 从 2026 年改用「年份.次版本」命名(26.1、26.2)后,版本号比较很容易出错。
SnowyGems 的做法是启动时读服务端的注册表,把当前实际存在的属性、附魔、药水效果、物品读成一份快照,之后所有查询都基于这份快照。
这带来三个直接好处:
新版本自动支持
低版本优雅降级
数据包内容也认
查看当前版本支持什么
/sgem compat # 简报
/sgem compat all # 完整清单 + 配置自检明细
输出包含:
- 服务端实现与版本
- 注册表规模(属性/附魔/效果/物品各多少项)
AttributeModifier用的是新 API 还是旧 API- 逐项能力探测结果(支持 / 当前版本没有 + 需要什么版本)
- 功能模块启停状态
- 配置自检结果
启动时也会打印简报,可以在 config.yml 里用 Compat.ReportOnStartup: false 关掉(仍可用命令随时查看)。
各版本新增内容一览
插件已把这些内容纳入探测清单,配置里可以直接写:
物品
| 内容 | 引入版本 | 配置里怎么写 |
|---|---|---|
| 锤 MACE | 1.21 | Require: [MACE] |
| 矛 SPEAR | 1.21.11 | Require: [SPEAR]、~onHit:SPEAR |
| 铜盔甲 / 铜工具 | 1.21.9 | Require: [COPPER_*] |
| 狼铠 WOLF_ARMOR | 1.20.5 | Require: [WOLF_ARMOR] |
| 刷子 BRUSH | 1.20 | Require: [BRUSH] |
属性
| 属性 | 引入版本 | 简写 |
|---|---|---|
scale 体型 | 1.20.5 | scale / size |
block_interaction_range 方块交互距离 | 1.20.5 | block_reach |
entity_interaction_range 实体交互距离 | 1.20.5 | attack_reach / entity_reach |
jump_strength 跳跃力 | 1.20.5 | jump |
gravity 重力 | 1.20.5 | gravity |
max_absorption 吸收上限 | 1.20.5 | absorption |
safe_fall_distance 安全落地距离 | 1.20.5 | safe_fall |
fall_damage_multiplier 落地伤害倍率 | 1.20.5 | fall_damage |
submerged_mining_speed 水下挖掘速度 | 1.21.2 | water_mining |
mining_efficiency 挖掘效率 | 1.21.2 | mining_efficiency |
movement_efficiency 移动效率 | 1.21.2 | movement_efficiency |
burning_time 燃烧时长 | 1.21.2 | burning_time |
oxygen_bonus 氧气加成 | 1.21.2 | oxygen_bonus |
sneaking_speed 潜行速度 | 1.21.2 | sneaking_speed |
sweeping_damage_ratio 横扫伤害比 | 1.21 | sweeping |
waypoint_transmit_range 路径点广播 | 26.x | 同名 |
waypoint_receive_range 路径点接收 | 26.x | 同名 |
camera_distance 视角距离 | 26.x | 同名 |
附魔(锤专属)
| 附魔 | 引入版本 |
|---|---|
density 密度 | 1.21 |
breach 穿透 | 1.21 |
wind_burst 风爆 | 1.21 |
药水效果(试炼密室)
| 效果 | 引入版本 |
|---|---|
oozing 渗浆 | 1.21 |
infested 寄生 | 1.21 |
weaving 盘丝 | 1.21 |
wind_charged 蓄风 | 1.21 |
trial_omen 试炼预兆 | 1.21 |
raid_omen 袭击预兆 | 1.21 |
旧名兼容
1.20.5 起 Mojang 把附魔、药水效果、属性都从静态常量改成了注册表,旧名(DURABILITY、DAMAGE_RESISTANCE、GENERIC_MAX_HEALTH)在新版本已经不存在。
插件内置了旧名 → 新键的映射表,老配置不用改:
| 你写的 | 实际解析成 |
|---|---|
DURABILITY | unbreaking |
DAMAGE_ALL | sharpness |
LOOT_BONUS_BLOCKS | fortune |
ARROW_INFINITE | infinity |
DAMAGE_RESISTANCE | resistance |
FAST_DIGGING | haste |
INCREASE_DAMAGE | strength |
JUMP | jump_boost |
GENERIC_MAX_HEALTH | max_health |
三种写法都能用:项目简写(health)、现代注册表键(max_health、minecraft:scale)、旧 Bukkit 常量名(GENERIC_MAX_HEALTH)。
unbreaking、sharpness、resistance),和游戏内 /enchant、/effect 的补全一致,不容易记错。功能模块开关
config.yml 的 Compat.Modules 下有 7 个模块,每个可取三种值:
| 值 | 含义 |
|---|---|
auto | 由服务端注册表决定:有就启用,没有就停用(默认,推荐) |
true | 强制启用。注册表里没有时相关配置会报「跳过」 |
false | 强制停用。即使服务端支持也不启用 |
| 模块 | 管辖内容 |
|---|---|
Mace | 锤及其专属附魔(密度/穿透/风爆) |
Spear | 矛(分类匹配、~onHit:SPEAR 触发) |
CopperEquipment | 铜盔甲与铜工具纳入 ARMOR / TOOL 分类 |
ModernAttributes | 1.20.5+ 新属性(scale、交互距离、重力等) |
MiningAttributes | 1.21.2+ 挖掘与移动类属性 |
TrialEffects | 1.21+ 试炼密室药水效果 |
WaypointAttributes | 26.x 路径点属性 |
模块停用后,它管辖的属性/附魔/效果/物品在查询时一律返回「不存在」,上层按既有的「跳过并提示」路径处理。
auto 已经能正确处理绝大多数情况。手动改的场景只有一个:混服。混服策略
如果你有多个不同版本的子服,共用同一份配置:
保持 auto(推荐)
什么都不用改。高版本子服自动启用新内容,低版本子服自动跳过。代价是低版本控制台会有「N 处内容当前版本不支持,已跳过」的提示。
低版本子服手动关掉高版本模块
如果嫌那条提示烦,在低版本子服的 config.yml 里把对应模块设为 false:
Compat:
Modules:
Spear: false # 这个子服是 1.21.4,没有矛
WaypointAttributes: false # 也没有 26.x 的路径点属性
这样 Require: [WEAPON] 在这个子服上就不会把矛算进去,配置自检也不再提示它们。
上线前用 strict 自检
正式服上线前把 OnMissingFeature 改成 strict,重载一次,控制台会用醒目的错误级别列出所有真正写错的条目。确认干净后再改回 skip。
配置自检的两类问题
自检会区分两种情况,这个区分很重要:
| 类型 | 例子 | 处理 |
|---|---|---|
| 版本不支持 | 1.21.4 上写了 Require: [SPEAR] | 正常状态,只记 Debug 日志 + 一行概要 |
| 写错了 | 写了 Enchant{name=sharpnes}(拼错) | 任何版本都不会生效,明确报出来 |
判据是模块归属表:归某个版本模块管的键算「版本不支持」,其余算「写错了」。写错的条目会带上拼写建议(如「你是不是想写: sharpness」)。
OnMissingFeature 三个级别的差异只影响「写错了」这一类的输出方式:
| 级别 | 行为 |
|---|---|
skip | 一行概要 + Debug 明细(默认) |
warn | 用 WARNING 级别逐条输出 |
strict | 用 SEVERE 级别逐条输出 |
三种级别都不会阻止插件启动。
AttributeModifier 的 API 差异
这是插件里唯一真正需要按版本分支的地方,插件已经处理好,写在这里供参考:
| 版本 | 构造函数 |
|---|---|
| 1.20.4 及以前 | AttributeModifier(UUID, String, double, Operation, EquipmentSlot) |
| 1.20.5 起 | AttributeModifier(NamespacedKey, double, Operation, EquipmentSlotGroup) |
| 1.21.9 前后 | 部分服务端实现开始移除旧构造 |
插件优先用新 API,用反射探测可用性并缓存结果。清理旧修饰符时同时按 NamespacedKey 和 UUID 两种身份匹配——因为玩家的装备可能是在插件用旧 API 的版本上镶嵌的,服务器升级后如果只按新 key 清理,旧修饰符会永久残留并持续叠加。
/sgem compat 会显示当前用的是哪套 API。
slot 的槽位组语义(any、armor、any_hand)是 1.20.5+ 才有的。在只支持旧 API 的服务端上,这几个值会退化成主手。
常见问题
升级服务端版本后要做什么?
理论上什么都不用做。跑一次 /sgem compat 确认新版本能力被识别到即可。如果之前手动关过模块,记得把它们改回 auto。
降级服务端版本后呢?
同样什么都不用做,高版本内容会自动跳过。想让控制台干净些,把对应模块设为 false。
为什么我的新属性宝石没效果?
按顺序检查:
/sgem compat all确认这个属性在你的版本上存在- 确认没有手动把对应模块设成
false - 检查
limit和var是否同号(这是最常见的原因,见宝石配置) - 开
/sgem debug Reward看这条 Rewards 的实际执行结果