114 lines
4.1 KiB
JavaScript
114 lines
4.1 KiB
JavaScript
import { readFile, writeFile, mkdir, copyFile } from "node:fs/promises";
|
|
import { existsSync } from "node:fs";
|
|
import { createHash } from "node:crypto";
|
|
import { spawn } from "node:child_process";
|
|
import { gunzipSync } from "node:zlib";
|
|
import { renderSnapshot } from "../renderer/render.mjs";
|
|
import { prepareAssets } from "./assets.mjs";
|
|
const directory = ".cache/paper-proof";
|
|
await mkdir(`${directory}/plugins`, { recursive: true });
|
|
const jar = `${directory}/paper.jar`;
|
|
if (!existsSync(jar)) {
|
|
const builds = await (
|
|
await fetch(
|
|
"https://fill.papermc.io/v3/projects/paper/versions/1.21.11/builds",
|
|
{ headers: { "User-Agent": "MineGeo/0.1 local development" } },
|
|
)
|
|
).json();
|
|
const build = builds.find((b) => b.channel === "STABLE");
|
|
const download = build.downloads["server:default"];
|
|
const bytes = Buffer.from(await (await fetch(download.url)).arrayBuffer());
|
|
if (
|
|
createHash("sha256").update(bytes).digest("hex") !==
|
|
download.checksums.sha256
|
|
)
|
|
throw new Error("Paper checksum mismatch");
|
|
await writeFile(jar, bytes);
|
|
}
|
|
await copyFile(
|
|
"minecraft/plugin/build/libs/minegeo-plugin-1.21.11.jar",
|
|
`${directory}/plugins/minegeo.jar`,
|
|
);
|
|
// This disposable loopback-only server exists solely for the requested integration test.
|
|
await writeFile(`${directory}/eula.txt`, "eula=true\n");
|
|
await writeFile(
|
|
`${directory}/server.properties`,
|
|
"server-ip=127.0.0.1\nserver-port=25579\nonline-mode=true\nlevel-seed=928341\nview-distance=5\nsimulation-distance=2\nspawn-protection=0\nenable-rcon=false\nmax-players=1\n",
|
|
);
|
|
if (!existsSync(`${directory}/plugins/MineGeo/export/terrain.json.gz`)) {
|
|
await new Promise((resolve, reject) => {
|
|
const child = spawn("java", ["-Xmx2G", "-jar", "paper.jar", "--nogui"], {
|
|
cwd: directory,
|
|
stdio: ["pipe", "pipe", "pipe"],
|
|
});
|
|
let ready = false,
|
|
exported = false,
|
|
buffer = "";
|
|
const timer = setTimeout(() => {
|
|
child.stdin.write("stop\n");
|
|
reject(new Error("Paper proof timed out"));
|
|
}, 240000);
|
|
process.once("SIGINT", () => child.stdin.write("stop\n"));
|
|
const output = (data) => {
|
|
const text = data.toString();
|
|
process.stdout.write(text);
|
|
buffer = (buffer + text).slice(-20000);
|
|
if (!ready && buffer.includes("Done (")) {
|
|
ready = true;
|
|
// The fixture explicitly generates its test area before export. The production
|
|
// plugin never generates chunks. No player connects during this test.
|
|
child.stdin.write("forceload add -48 -48 47 47\n");
|
|
setTimeout(
|
|
() =>
|
|
child.stdin.write(
|
|
"fill -47 99 -47 47 99 47 minecraft:grass_block\nfill -6 100 -6 6 103 6 minecraft:stone_bricks\nfill -5 104 -5 5 105 5 minecraft:oak_planks\nfill 16 100 16 24 100 24 minecraft:water\nminegeo area world -48 -48 48 48\nminegeo export Paper Proof\n",
|
|
),
|
|
12000,
|
|
);
|
|
}
|
|
if (!exported && buffer.includes("Export complete:")) {
|
|
exported = true;
|
|
child.stdin.write("stop\n");
|
|
}
|
|
if (!exported && text.includes("Export failed:"))
|
|
child.stdin.write("stop\n");
|
|
};
|
|
child.stdout.on("data", output);
|
|
child.stderr.on("data", output);
|
|
child.on("exit", (code) => {
|
|
clearTimeout(timer);
|
|
exported
|
|
? resolve()
|
|
: reject(new Error(`Paper exited ${code} without an export`));
|
|
});
|
|
});
|
|
}
|
|
const source = `${directory}/plugins/MineGeo/export`;
|
|
const manifest = JSON.parse(await readFile(`${source}/manifest.json`, "utf8"));
|
|
const terrain = JSON.parse(
|
|
gunzipSync(await readFile(`${source}/terrain.json.gz`)).toString(),
|
|
);
|
|
await prepareAssets();
|
|
const report = await renderSnapshot(
|
|
terrain,
|
|
manifest.viewpoints,
|
|
"public/generated/paper-proof",
|
|
{ size: 1024 },
|
|
);
|
|
await mkdir(".data/fixtures", { recursive: true });
|
|
await copyFile(`${source}/manifest.json`, ".data/fixtures/paper-proof.json");
|
|
await writeFile(
|
|
"artifacts-renderer-proof.json",
|
|
JSON.stringify(
|
|
{
|
|
...report,
|
|
source: "real Paper 1.21.11 terrain snapshot",
|
|
bounds: manifest.bounds,
|
|
viewpoints: manifest.viewpoints.length,
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
console.log("RENDERER PROOF:", JSON.stringify(report));
|