Files
MagicGem-Reforged/MIGRATION.md
T

459 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MagicGem 迁移指南
本文说明如何从原版 MagicGem 或之前的 CMagicGem 重实现迁移到当前版本。迁移范围包括插件 JAR、配置文件、宝石、技能、GUI、语言文件,以及玩家物品中的宝石数据。
当前版本面向 Minecraft/Paper 1.21.x(包括 1.21.11),使用 Java 21。插件保留原插件的非授权功能,不实现网络授权或机器绑定。
## 迁移前的目录和插件身份
当前插件的身份仍然是 `MagicGem`:
```yaml
name: MagicGem
main: pku.yim.magicgem.MagicGem
```
主命令是 `/mgem`,别名是 `/cmgem` 和 `/cmg`。新旧 JAR 不能同时运行,因为它们使用相同的插件名、数据目录和命令。
常见的数据目录有四种情况:
```text
# 原版 MagicGem
plugins/
└─ MagicGem/
# 之前的 CMagicGem 重实现
plugins/
└─ CMagicGem/
# 两个目录同时存在
plugins/
├─ MagicGem/
└─ CMagicGem/
# 全新安装
plugins/
```
当前版本始终把 `plugins/MagicGem` 作为有效目录。`plugins/CMagicGem` 只作为旧数据来源导入。
## 第一次迁移前的准备
1. 停止服务器,不能在服务器运行时替换 JAR 或修改插件数据。
2. 备份整个服务器,至少包括以下内容:
```text
plugins/MagicGem/
plugins/CMagicGem/
world/
world_nether/
world_the_end/
```
玩家背包、末影箱、容器和世界区块中的物品数据不在插件目录中,只备份插件目录不足以完整回滚。
3. 移除旧版 MagicGem JAR 和旧版 CMagicGem JAR。
4. 将当前版本 JAR 放入 `plugins/`。
5. 保留 `plugins/MagicGem` 和 `plugins/CMagicGem`,不要在第一次启动前删除旧目录。
6. 使用 Java 21 启动 Paper 1.21.x。
## 启动时的执行顺序
当前插件启动时会按照以下顺序工作:
1. Paper 读取 `plugin.yml`,以 `MagicGem` 身份加载插件。
2. `onLoad()` 预加载 NBT API。
3. 执行旧目录导入器,检查 `plugins/CMagicGem`。
4. 如果缺少默认 `config.yml`,创建当前版本的默认配置。
5. 只为不存在的文件写入内置宝石、技能、GUI 和语言资源。
6. 读取语言配置。
7. 初始化宝石注册表、技能注册表、GUI、物品编解码器和软依赖集成。
8. 执行完整 reload,读取配置并加载宝石、技能和 GUI。
9. 注册 `/mgem` 命令和事件监听器。
10. 输出集成状态和已加载宝石数量。
迁移必须发生在宝石和技能注册表加载之前。物品里保存的是宝石名或技能名,完整定义仍然来自 `gems/*.yml` 和 `skills/*.yml`。
## 情况一:只有原版 `plugins/MagicGem`
这种情况下不需要复制或重命名目录。当前版本会直接沿用:
```text
plugins/MagicGem/config.yml
plugins/MagicGem/gems/*.yml
plugins/MagicGem/skills/*.yml
plugins/MagicGem/gui/*.yml
plugins/MagicGem/languages/*.yml
```
迁移器发现当前数据目录就是 `plugins/MagicGem` 后会跳过目录导入。已有配置不会被默认配置覆盖,已有资源文件也不会被内置资源覆盖。
旧配置中的以下写法都可以读取:
```yaml
lang: zh_CN
```
或:
```yaml
language: zh_CN
```
操作流程就是停止服务器、替换 JAR、保留 `plugins/MagicGem`、启动服务器。
## 情况二:只有 `plugins/CMagicGem`
如果不存在 `plugins/MagicGem`,但存在 `plugins/CMagicGem`,当前版本会创建 `plugins/MagicGem`,并导入以下内容:
```text
CMagicGem/gems → MagicGem/gems
CMagicGem/skills → MagicGem/skills
CMagicGem/gui → MagicGem/gui
CMagicGem/languages → MagicGem/languages
CMagicGem/config.yml → MagicGem/config.yml
```
旧的 `plugins/CMagicGem` 源目录不会被删除,也不会被修改。
如果旧目录没有 `config.yml`,插件会在后续启动阶段创建当前版本默认配置。如果旧目录有配置而目标目录没有配置,插件会先创建默认配置,再用旧配置中的值覆盖对应默认项,同时保留新版本新增的配置项。
## 情况三:两个目录同时存在
当两个目录都存在时:
```text
plugins/MagicGem/ # 有效目录,优先级高
plugins/CMagicGem/ # 旧目录,作为补充来源
```
迁移器只从 `CMagicGem` 补充目标目录中缺少的文件和配置项。`MagicGem` 中已经存在的内容优先保留。
例如旧文件是:
```yaml
Shared:
Name: Old Name
Material: DIAMOND
OldOnly: retained
```
当前目录中的文件是:
```yaml
Shared:
Name: Current Name
Material: DIAMOND
CurrentOnly: retained
```
合并后的目标文件是:
```yaml
Shared:
Name: Current Name
Material: DIAMOND
OldOnly: retained
CurrentOnly: retained
```
也就是说,目标目录中的 `Name` 优先,旧目录独有的 `OldOnly` 会补入,目标目录独有的 `CurrentOnly` 也会保留。
## 文件合并规则
迁移器处理以下目录:
```text
gems/
skills/
gui/
languages/
```
每个文件按照以下规则处理:
| 情况 | 行为 |
| --- | --- |
| 目标文件不存在 | 从 `CMagicGem` 复制到 `MagicGem` |
| YAML 文件同名且内容不同 | 递归合并,目标值优先 |
| YAML 中只有旧目录存在的配置项 | 补入目标文件 |
| YAML 中双方值不同 | 保留 `MagicGem` 值,记录冲突 |
| 非 YAML 文件内容相同 | 跳过 |
| 非 YAML 文件内容不同 | 保留目标文件,记录冲突 |
| 目标文件已存在 | 不直接覆盖 |
YAML 合并可以处理同一个文件中不同的宝石、技能或语言段落,而不是简单地按文件覆盖。
## `config.yml` 合并规则
如果目标目录中没有 `config.yml`:
1. 先生成当前版本默认配置。
2. 导入旧配置中的字段。
3. 旧配置存在的值覆盖默认值。
4. 旧配置不存在的新字段继续保留默认值。
例如当前默认配置是:
```yaml
language: zh_CN
workbench: true
backpack: false
```
旧配置是:
```yaml
lang: en_US
backpack: true
```
最终结果会保留旧设置和新默认项,效果类似:
```yaml
language: en_US
lang: en_US
workbench: true
backpack: true
```
如果目标配置已经存在,则目标配置优先,旧配置中目标没有的字段会补入:
```yaml
# MagicGem/config.yml
language: zh_CN
backpack: false
```
```yaml
# CMagicGem/config.yml
language: en_US
backpack: true
old-option: kept
```
最终目标配置会保持:
```yaml
language: zh_CN
backpack: false
old-option: kept
```
## 冲突备份
发生冲突时,旧源文件会保存到:
```text
plugins/MagicGem/migration-backup/CMagicGem/
```
例如:
```text
plugins/CMagicGem/gems/Shared.yml
```
会备份为:
```text
plugins/MagicGem/migration-backup/CMagicGem/gems/Shared.yml
```
配置文件冲突则会备份为:
```text
plugins/MagicGem/migration-backup/CMagicGem/config.yml
```
控制台会列出冲突字段,并说明 `MagicGem` 的值被保留。旧源目录本身保持不变。
如果源文件和目标文件内容完全相同,不会被当作冲突,也不会产生额外备份。
## 迁移完成标记
完整迁移成功后会创建:
```text
plugins/MagicGem/.migration-cmagicgem-v1.complete
```
该标记用于防止每次服务器启动都重复执行相同迁移。
如果第一次迁移过程中发生 IO 错误或 YAML 格式错误:
- 不会写入完成标记;
- 不会删除旧源目录;
- 控制台会输出错误日志;
- 下次启动会再次尝试迁移。
如果迁移完成后又修改了 `plugins/CMagicGem`,这些新修改不会自动再次导入,因为完成标记已经存在。需要重新导入时,应先停止服务器、备份当前 `plugins/MagicGem`、删除完成标记,再重新启动。
## 玩家物品的迁移方式
插件目录迁移和玩家物品迁移是两个独立过程。
当前版本不会在启动时遍历所有玩家背包并一次性重写全部物品,而是采用兼容读取和延迟迁移。物品在被识别、镶嵌、拆卸、强化或执行技能相关操作时,才会逐步写入当前格式。
物品可能包含以下数据格式:
```text
当前 MagicGem PDC
旧 CMagicGem PDC
原版 MagicGem NBT
Lore 标识
```
当前版本会依次尝试读取:
```text
magicgem:gem_name
cmagicgem:gem_name
MAGICGEM_NAME
```
如果允许使用 Lore 识别,还会把宝石 Lore 作为备用依据。
### 宝石名称
原版物品通常包含:
```text
MAGICGEM_NAME
```
当前版本会使用这个名称去查找已经加载的宝石定义。识别成功后会写入当前 PDC:
```text
magicgem:gem_name
```
原版 `MAGICGEM_NAME` 作为兼容字段继续保留。新创建的宝石也会同时写入当前标识和原版名称字段。
如果物品中的宝石名称存在,但 `gems/*.yml` 没有迁移或加载失败,插件无法恢复完整宝石定义。
### 镶嵌内容
原版镶嵌数据通常位于:
```text
MAGICGEM_EMBED
```
它是一个包含宝石名称和数量的复合 NBT,例如:
```text
{
"AttributeGem": 2,
"EnchantGem": 1
}
```
当前版本会按以下顺序读取:
1. `magicgem:embedded_gems`;
2. `cmagicgem:embedded_gems`;
3. `MAGICGEM_EMBED`;
4. 兼容旧格式的嵌套 NBT。
读取旧 NBT 后,物品在后续使用时会写入当前 PDC,同时继续写入兼容的 `MAGICGEM_EMBED`。执行镶嵌或拆卸时,这个受插件管理的字段会被重新整理;其他无关物品数据不会被主动删除。
### 技能列表
原版技能数据通常位于:
```text
MAGICGEM_SKILL
```
当前版本会按以下顺序读取:
```text
magicgem:skills
cmagicgem:skills
MAGICGEM_SKILL
```
读取成功后,技能名称会按当前格式保存,并继续写入兼容的 `MAGICGEM_SKILL`。技能是否能实际执行,还取决于对应的 `skills/*.yml` 是否已经加载。
## 启动后的检查
迁移成功时,控制台应出现类似日志:
```text
Imported plugins/CMagicGem into plugins/MagicGem: X files copied, Y files merged, Z files with conflicts.
```
插件正常启用时,应出现类似日志:
```text
MagicGem 已启用,命令 /mgem,加载 N 颗宝石。
```
建议执行以下检查:
```text
/mgem view
/mgem get
/mgem embed
/mgem reload
```
还应实际测试:
- 旧宝石是否可以识别;
- 旧镶嵌装备是否显示正确;
- 拆卸和重新镶嵌是否正常;
- 技能是否能够触发;
- GUI 是否可以打开;
- 中文或英文语言是否正确;
- Vault、PlayerPoints、PlaceholderAPI、MythicMobs 等软依赖是否正常;
- 服务器重启后数据是否仍然存在。
如果日志显示宝石数量明显少于旧版本,应优先检查 `plugins/MagicGem/gems/` 中的 YAML 是否完整,以及控制台是否有宝石解析错误。
## 回滚方式
最安全的回滚方式是停止服务器并恢复迁移前的完整备份:
1. 停止服务器。
2. 备份当前运行后的日志和数据,方便排查问题。
3. 恢复旧版 MagicGem JAR。
4. 恢复原来的 `plugins/MagicGem`。
5. 必要时恢复玩家数据和世界备份。
6. 启动服务器验证。
如果只有 `plugins/CMagicGem`,迁移器不会删除它,因此它可以继续作为旧配置来源。但是如果新版本运行期间已经改变了玩家物品或世界数据,仍然建议恢复完整服务器备份,而不是只恢复插件 JAR。
## 当前实现的注意事项
配置文件包含:
```yaml
legacy-migration: true
```
但当前启动代码在读取配置前就调用目录导入器,因此这个开关目前不会阻止 `CMagicGem` 目录迁移。正常升级不需要修改它;如果以后需要支持关闭迁移,应将导入调用调整到配置加载之后,并显式检查该设置。
另外,目录识别使用的旧目录名是准确的:
```text
plugins/CMagicGem
```
其他自定义目录名不会被自动扫描。需要使用其他目录名时,应在停服并备份后手动改名为 `CMagicGem`,或者手动合并文件。
## 迁移完成检查清单
- [ ] 已停止服务器并备份插件、世界和玩家数据。
- [ ] 已移除旧版 MagicGem/CMagicGem JAR。
- [ ] 新 JAR 已放入 `plugins/`。
- [ ] `plugins/MagicGem` 已保留。
- [ ] `plugins/CMagicGem` 在确认迁移成功前已保留。
- [ ] 控制台显示迁移结果或明确显示没有旧目录。
- [ ] 没有未处理的 YAML 解析错误。
- [ ] 宝石数量与预期一致。
- [ ] 旧宝石、镶嵌装备和技能已实际测试。
- [ ] GUI、语言和软依赖功能已测试。
- [ ] 已保存冲突备份和迁移前备份。
- [ ] 已重启服务器确认数据仍然正常。