数据包格式与优先级
基本信息
| 属性 | 值 |
|---|---|
| 加载器 | databack.common.loader.DatapackLoader(类注释自述为「加载世界全部数据包的唯一入口」) |
| 目标格式版本 | LOADER_FORMAT_VERSION = 48(DatapackLoader.java:62,仅用于 overlay 解析) |
| 用户数据包目录 | <世界存档>/datapacks/(DatapackLoader.java:85) |
| 支持的包形态 | 目录,或 .zip 文件(后缀判断大小写不敏感,DatapackLoader.java:256) |
| 内置原版包 | 启动时从 Mojang 下载 MC 26.1 的 data/ 作为最低优先级基线 |
| 顺序持久化 | 世界 NBT 的 Order(顺序表)与 Disabled(禁用集合)两个字符串列表 |
功能
定义 Databack 如何发现、解析、排序数据包,以及这些状态如何写进世界存档。
候选发现
discoverCandidates(File worldSaveDir)(DatapackLoader.java:69-97)按顺序产出候选:
- 原版数据包置索引 0,最低优先级 —— 注释明写「Vanilla datapack at index 0 (lowest priority — every other pack overrides it)」。游戏目录由
worldSaveDir.getParentFile().getParentFile()推导,即从世界存档目录上溯两级得到.minecraft(DatapackLoader.java:72-79) <世界存档>/datapacks/下的内容;目录不存在时只记一条Datapack directory does not exist: ...的 INFO 日志,不报错(DatapackLoader.java:87-92)- 发出
DatapackGatherEvent(candidates),允许其他模组追加候选(DatapackLoader.java:95)
discover 扫描 datapacks/ 的一级子项:子目录全部纳入;文件仅当小写后缀为 .zip 时纳入;返回顺序为文件系统顺序(DatapackLoader.java:246-261)。包名由 derivePackName 取目录名或去掉 .zip 的文件名(DatapackLoader.java:596-602,.zip 判断在 :598)。
包形态解析:目录走 FolderDatapackSource,压缩包走 ZipDatapackSource;缺少 pack.mcmeta 的候选直接返回 null 被跳过,解析失败则抛 DatapackLoadException(DatapackLoader.java:275-293)。
排序与优先级
优先级规则由源码与指令帮助文本共同确证:
| 规则 | 说明 | 出处 |
|---|---|---|
| 列表靠后者优先级更高 | 指令帮助明写「Packs at the end/bottom of the list have priority over earlier packs.」 | DatapackCommand.java:65 |
| 资源迭代从高到低 | 「Iterates all packs (highest priority first)」,orderedPacks 为低→高顺序,for (oi = size-1; oi >= 0; oi--) 反向遍历 |
DatapackLoader.java:345-370 |
| 排序表内下标越小优先级越低 | db$order 用 Comparator.comparingInt(pack -> db$datapackOrder.indexOf(pack.getPackId())) 升序排序,找不到时取 Integer.MAX_VALUE(即沉到末尾) |
MixinWorldInfo_Datapacks.java:116-134 |
| 原版包恒为最低 | 固定插在候选索引 0 | DatapackLoader.java:72 |
新出现的包在 db$syncPackDeltas(MixinWorldInfo_Datapacks.java:102-113)中被追加到顺序表末尾,因此默认获得较高优先级(:110);已从磁盘消失的包会从顺序表和禁用集合中一并剔除(同方法 removeIf)。
pack.mcmeta 与 overlays
PackMetadata 解析出四组字段:getPack()(PackInfo)、getFilter()(PackFilter)、getOverlays()(PackOverlays)、getFeatures()(PackFeatures)(PackMetadata.java:42-57)。
Overlay 解析规则:
- 只对目标格式版本
LOADER_FORMAT_VERSION = 48生效(DatapackLoader.java:376) - overlay 目录按列出顺序的反序枚举,即「最后列出者优先」(
DatapackLoader.java:378-379) - 每个 overlay 目录下的数据前缀是
<dir>/data/(DatapackLoader.java:385) - 空 overlay 目录被静默跳过(
DatapackLoader.java:388-389) - overlay 目录名会经
validateOverlayDirectoryName校验,注释明写目的是「不包含路径穿越字符」,空目录名抛异常(DatapackLoader.java:431-438) - 同一包内 overlay 优先于包基础
data/(DatapackLoader.java:345注释:先枚举 overlays 再 base)
存档持久化
顺序与禁用状态存放在 WorldInfo 上,由 Mixin 注入两个字段实现(MixinWorldInfo_Datapacks.java:30、33):
| 字段 | NBT 键 | 类型 | 含义 |
|---|---|---|---|
db$datapackOrder |
Order |
NBTTagList of NBTTagString |
包的启用顺序(升序,末尾优先级最高) |
db$disabledDatapacks |
Disabled |
NBTTagList of NBTTagString |
被 /datapack disable 的包 id 集合 |
读写链路为 DatapackModContainer(IFMLLoadingPlugin.getModContainerClass() 指定该类,父容器 modid 为 databackcore):
- 存盘:
getDataForWriting调用((DatapackWorldInfo) info).db$saveDatapackInfo()(DatapackModContainer.java:42-44) - 读档:
readData调用db$loadDatapackInfo(tag)恢复状态,随后DatapackLoader.load(handler.getWorldDirectory(), ...)重新加载(DatapackModContainer.java:47-50) - 读入
db$loadDatapackInfo见MixinWorldInfo_Datapacks.java:35-50,其中Disabled列表通过 Mixin 生成的AccessorNBTTagList强转遍历字符串列表(:42);写出db$saveDatapackInfo见:61-80 WorldInfo的复制构造器被 Mixin 注入@Inject(method = "<init>(Lnet/minecraft/world/storage/WorldInfo;)V", at = @At("TAIL")),把源实例的顺序与禁用集合一并复制(MixinWorldInfo_Datapacks.java:52-62)
原版数据包下载
VanillaDatapackDownloader(DatapackLoader.java:76、CommonProxy.java:103-108):
| 属性 | 值 |
|---|---|
| 目标版本 | MC_VERSION = "26.1"(VanillaDatapackDownloader.java:24) |
| 版本清单 | https://piston-meta.mojang.com/mc/game/version_manifest_v2.json(VanillaDatapackDownloader.java:25-26) |
| 缓存目录名 | vanilla-datapack-26.1(VanillaDatapackDownloader.java:27) |
| 只取 | data/ 目录与 pack.mcmeta(类注释 VanillaDatapackDownloader.java:14) |
| 合成 meta | 缺失时写出 {"pack":{"pack_format":48,"description":"<版本> datapack"}}(VanillaDatapackDownloader.java:426) |
| User-Agent | Databack-Mod/26.1(VanillaDatapackDownloader.java:377) |
| 失败处理 | discoverCandidates 记 ERROR 日志「Failed to obtain vanilla datapack; world generation may be incomplete」并继续;preInit 侧记 ERROR「Failed to download vanilla datapack during boot」 |
Gradle 侧有配套的构建期任务 downloadVanillaDatapack,用同样的 MC_VERSION = "26.1" 抽取 data/ 到 build/modernData(addon.gradle)。仓库内 misc/test-packs/minecraft/data 是指向 ../../../build/modernData/data 的符号链接。
源码中一处测试用候选路径
discoverCandidates 末尾无条件追加了一条候选(DatapackLoader.java:93):
candidates.add(worldSaveDir.toPath().resolve("..").resolve("..").resolve("..").resolve("..").resolve("misc/test-packs/minecraft").toFile());
即从世界存档目录上溯四级再进入 misc/test-packs/minecraft(仓库内的测试包)。该路径在普通安装的 .minecraft 下并不存在;按 loadCandidate 的规则,缺少 pack.mcmeta 的候选会被跳过。此处仅陈述源码事实,运行时行为未实测。
资源位置组件校验
加载器使用 Pattern.compile("[a-z0-9_.\\-]+") 校验资源位置各组件(DatapackLoader.java:65,注释:「Regex patterns for resource location component validation」)。
相关条目
- 数据包资源类型 - 19 类资源路径与处理器
- /datapack 指令 - 调整
Order与Disabled的操作入口 - 依赖与集成 -
databackcore容器、GTNHLib、MCGPU