import { mkdir, readFile, writeFile, access } from "node:fs/promises"; import { createHash } from "node:crypto"; import { unzipSync } from "fflate"; export const assetsRoot = ".cache/minecraft/1.21.11"; export async function prepareAssets() { try { await access(`${assetsRoot}/assets/minecraft/blockstates/grass_block.json`); return; } catch {} const manifest = await ( await fetch( "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json", ) ).json(); const entry = manifest.versions.find((v) => v.id === "1.21.11"); if (!entry) throw new Error("Official Minecraft 1.21.11 metadata missing"); const version = await (await fetch(entry.url)).json(); await mkdir(".cache/minecraft", { recursive: true }); const jarPath = ".cache/minecraft/client-1.21.11.jar"; let jar; try { jar = await readFile(jarPath); } catch { const response = await fetch(version.downloads.client.url); if (!response.ok) throw new Error("Minecraft asset download failed"); jar = Buffer.from(await response.arrayBuffer()); await writeFile(jarPath, jar); } if ( createHash("sha1").update(jar).digest("hex") !== version.downloads.client.sha1 ) throw new Error("Minecraft client checksum mismatch"); const entries = unzipSync(jar, { filter: (f) => /^assets\/minecraft\/(models|blockstates|textures\/block)\//.test( f.name, ) && /\.(json|png)$/.test(f.name), }); for (const [name, bytes] of Object.entries(entries)) { const path = `${assetsRoot}/${name}`; await mkdir(path.slice(0, path.lastIndexOf("/")), { recursive: true }); await writeFile(path, bytes); } console.log( `Prepared ${Object.keys(entries).length} verified vanilla model/texture assets.`, ); }