SaveSection3D(三维存档区)

基本信息

属性 值
实现类 cubicchunks.regionlib.impl.save.SaveSection3D
继承 SaveSection<SaveSection3D, EntryLocation3D>
key 类型 EntryLocation3D(实现 IKey<EntryLocation3D>)
每区域条目数 ENTRIES_PER_REGION = (1 << 4) * (1 << 4) * (1 << 4) = 4096
区域文件名 <regX>.<regY>.<regZ>.3dr
目录 SaveCubeColumns.create() 里固定为 <directory>/region3d
扇区大小 512(SimpleRegionFactory.createDefault(..., 512))

⚠️ 这不是一个 Minecraft 维度。 本 mod 没有 WorldProvider / DimensionType / registerDimension。“3D"指存档数据空间是三维的(X/Y/Z 三个坐标轴,对应 Cubic Chunks 的"立方体 cube”),是为三维世界准备的分区方式,与下界/末地等游戏维度无关。

坐标 ↔ 区域 / id 的换算

private static final int LOC_BITS = 4;                 // 16
private static final int LOC_BITMASK = (1 << 4) - 1;   // 15
public static final int ENTRIES_PER_REGION = 4096;

getRegionKey() → new RegionKey(regX + "." + regY + "." + regZ + ".3dr")  // 各自 >> 4
getId()        → ((entryX & 15) << 8) | ((entryY & 15) << 4) | (entryZ & 15)
性质 说明
equals 比较 entryX / entryY / entryZ 三字段
hashCode 31 * (31 * entryX + entryY) + entryZ
字段访问 getEntryX() / getEntryY() / getEntryZ()
toString EntryLocation3D{entryX=…, entryY=…, entryZ=…}
可变性 三字段均 final

注意 2D / 3D 的粒度差 2 倍:2D 每区域 32×32(LOC_BITS = 5),3D 每区域 16×16×16(LOC_BITS = 4)。同为 X/Z 轴,2D 的区域边长是 3D 的两倍。

EntryLocation3D.Provider

方法 行为
getKeyCount(RegionKey) 恒返回 ENTRIES_PER_REGION = 4096
isValid(RegionKey) key.getName().matches("-?\\d+\\.-?\\d+\\.-?\\d+\\.3dr")
fromRegionAndId(RegionKey, int) 先 isValid,不通过抛 IllegalArgumentException("Invalid name " + regionKey.getName());relativeX = id >>> 8、relativeY = (id >>> 4) & 15、relativeZ = id & 15,还原为 new EntryLocation3D(regX << 4 | relativeX, regY << 4 | relativeY, regZ << 4 | relativeZ)

构造与工厂

签名 说明
SaveSection3D(IRegionProvider<EntryLocation3D>... regionProvider) 只有变参构造(super(Arrays.asList(regionProvider)))。与 SaveSection2D 不同,3D 版没有单 IRegionProvider 的便捷构造
static SaveSection3D createAt(Path directory) 标准两层回退装配

createAt(Path):

顺序 IRegionProvider 底层 IRegion 存在判定
1 SharedCachedRegionProvider(SimpleRegionFactory.createDefault(new EntryLocation3D.Provider(), directory, 512)) Region(512 B 扇区) Files.exists(directory.resolve(key.getName()))
2 SharedCachedRegionProvider(new SimpleRegionFactory<>(new EntryLocation3D.Provider(), directory, (kp, rk) -> new ExtRegion<>(directory, Collections.emptyList(), kp, rk), (kp, rk) -> Files.exists(directory.resolve(rk.getName() + ".ext")))) ExtRegion(.ext 目录) Files.exists(dir/<name>.ext)

两层的 keyProvider 都是 new EntryLocation3D.Provider(),扇区表能对上同一个 id 空间——这正是回退链能透明工作的前提。

数据访问

与 SaveSection2D 一样,SaveSection3D 本身不覆写任何数据方法。SaveCubeColumns 的对应入口:

方法 签名
单条写 save3d(EntryLocation3D location, ByteBuffer data)
批量写 save3d(Map<EntryLocation3D, ByteBuffer> entries)
单条读 load(EntryLocation3D location, boolean createRegion) → Optional<ByteBuffer>
批量读 load3D(Collection<EntryLocation3D> positions, boolean createRegion) → BatchReadResult<EntryLocation3D>
取本节 getSaveSection3D()

SaveCubeColumns.flush() / close() 会依次转发到 saveSection2D 和 saveSection3D。

数值

数值 值
单区域条目数 4096
单条目字节上限 130556(255 × 512 − 4);超出自动落 .ext
单区域头表扇区数 4096 × 4 = 16384 字节 = 32 扇区,开局即占用

对比:2D 版头表只要 8 扇区,3D 版要 32 扇区——3D 每个区域文件开头的固定开销是 2D 的四倍。

相关条目