Skip to content

投影工坊 ​

投影工坊是实验室里处理 Minecraft 投影(schematic)的一组工具:扫目录、读信息、改元数据、转格式,再加一个能走进去的 3D 预览。

扫的是哪两个目录 ​

只有两处:<.minecraft>/schematics 和 <.minecraft>/config/litematica——Litematica 和 WorldEdit 的默认落点。目录不存在就返回空表,不主动创建。

列表阶段只读文件名、大小、修改时间。真正的解包统计等用户点开某个文件才做,否则扫到几百个投影时界面会先卡一轮。

读出来能看什么 ​

尺寸(取 Metadata.EnclosingSize,没有就用各区域包围盒算)、区域数、方块统计(按出现次数倒序,前 24 种)、调色板大小、DataVersion。

方块统计是自己数出来的,不是读 Metadata.TotalBlocks:

csharp
// 用实际统计值:投影文件自带的 Metadata.TotalBlocks 是生成器写的,可能和内容对不上
// (实测 redenmc 生成的两个文件都写着 114514,而实际只有几千个方块)
TotalBlocks = totalBlocks,

超出 800 万格的投影按质数步长抽样统计再按步长放大。步长必须是质数:世吞这类投影排布有周期性,8/21 这种合数步长会共振,系统性漏掉整列——实测 26 万格被估成 8 万。

3D 预览用本机真实纹理 ​

预览不是近似色。每个方块的外观都从用户本机的 Minecraft 资源里读:blockstates/*.json 决定用哪个 model,models/*.json 给出贴图引用,最后去 textures/ 拿 png。资源来源按优先级分四层,从高到低:

  1. options.txt 里 resourcePacks 启用的资源包(越靠后优先级越高)
  2. 客户端 jar(versions/<id>/<id>.jar,原版方块外观的完整来源)
  3. 模组 jar(assets/<modid>/**)
  4. assets/indexes/ + objects/(老布局兜底)

必须是 jar 优先

现代版本的 assets/indexes/ 里没有 blockstates 和 models——实测索引 34 只有 sounds、lang 和 7 张纹理。所以"索引优先、索引缺失才回退 jar"这种顺序永远拿不到方块纹理,界面只会显示洋红占位块。jar 层必须排在索引层前面。

zip 句柄要缓存

解析一个方块要读 4~6 个资源(blockstate、model、几个 texture)。每次都重开 26MB 的客户端 jar,预览会拖到好几秒——实测 8370 项调色板 7.6 秒,加了句柄缓存之后降到 1 秒以内。所以 MinecraftAssets 用 Dictionary<string, ZipArchive> 缓存打开的 jar,句柄留着不挡别的进程更新版本。

方块几何(模型继承、元素旋转、多部件、UV、透明纹理)交给第三方库 deepslate(MIT)在页面里解析渲染。

空间模式 ​

点「空间模式」可以进到投影里自由走:WASD 移动、鼠标转视角、空格跳(双击空格切飞行)、Shift 下潜、Ctrl 加速、滚轮调速、Esc 退出。物理参数直接对齐原版手感:

javascript
const PLAYER = { width: 0.6, height: 1.8, eye: 1.62 };
const GRAVITY = 32, JUMP_V = 8.4, TERMINAL = 78;
const SPEED = { walk: 4.317, sprint: 5.612, fly: 10.92, flySprint: 21.6 };

碰撞是逐轴推进的 AABB:先算玩家包围盒覆盖的整数格,遇到实心格就贴边停下并把该轴速度清零。y 轴向下走时命中方块顶面会置 onGround = true,跳跃才成立。

出生点不是投影中心,而是"离中心最近的列里、地面最高的那一格"上方——不然会直接卡在墙里。出生时默认飞行,双击空格落地行走。

超大投影的取舍 ​

体素导出有 20 万个方块的预算。低于这个数全量直出,超过就降采样:按 cbrt(体积/预算) 算出格子边长,把 k³ 格压成一个占用格,保留整体轮廓,并如实标记"已截断"。

关键是绝不能整块解包成 int 数组。实测 998×81×2006 是 1.6 亿格,全解包是几百 MB 分配,直接把启动器拖死。所以一律用 ProjectionReader.ReadAt 逐位读。

相关链接:格式细节与位打包

基于 MIT 许可证(有修改)开源