Improve MineGeo exploration and mapping features

This commit is contained in:
2026-10-05 13:41:36 +05:00
parent aec0641f87
commit c5368fa8cc
69 changed files with 3581 additions and 333 deletions

View File

@@ -11,6 +11,7 @@ await new Promise((resolve, reject) => {
cwd: "minecraft",
stdio: "inherit",
shell: windows,
windowsHide: true,
});
child.on("error", reject);
child.on("exit", (code) =>

View File

@@ -30,6 +30,7 @@ const dataset = check(
if (
dataset.source !== "plugin" ||
dataset.revision_id ||
dataset.parent_dataset_id ||
!["draft", "rejected"].includes(dataset.state)
)
throw new Error(
@@ -52,6 +53,14 @@ const input = check(
.single(),
);
if (!input.validated) throw new Error("The export must be validated first.");
if (
(input.manifest.availableViewpoints ?? input.manifest.viewpoints).some(
(p) => p.assetRoot,
)
)
throw new Error(
"Repair mixed-media drafts by uploading a new capture; accepted contribution files cannot be overwritten.",
);
const asset = input.manifest.assets.find((a) => a.path === "terrain.json.gz");
if (!asset) throw new Error("Missing original terrain export");
const raw = check(

View File

@@ -29,10 +29,11 @@ const dataset = check(
);
if (
dataset.revision_id ||
dataset.parent_dataset_id ||
!["draft", "review", "rejected", "failed"].includes(dataset.state)
)
throw new Error(
"Only an unpublished, inactive draft can be reprocessed. Published revisions cannot be changed.",
"Only an unpublished, inactive original capture can be reprocessed. Published revisions cannot be changed. Contributions cannot be overwritten; upload a new capture instead.",
);
const job = check(
await client.from("upload_jobs").select("*").eq("dataset_id", id).single(),
@@ -48,6 +49,14 @@ const input = check(
.eq("dataset_id", id)
.single(),
);
if (
(input.manifest.availableViewpoints ?? input.manifest.viewpoints).some(
(p) => p.assetRoot,
)
)
throw new Error(
"This draft contains accepted contributions. Upload a new capture instead of reprocessing mixed media.",
);
if (dataset.source === "plugin") await prepareAssets();
// This maintenance command runs with the worker stopped. Compare-and-set

View File

@@ -26,6 +26,7 @@ let manifest: any,
creates = 0,
finalizes = 0,
heads = 0;
let expectedServer: string | null = "play.regression.example.com";
const api = createServer(async (req, res) => {
const chunks: Buffer[] = [];
for await (const chunk of req) chunks.push(chunk);
@@ -37,9 +38,24 @@ const api = createServer(async (req, res) => {
const origin = `http://127.0.0.1:${(api.address() as any).port}`;
if (req.url === "/api/v1/uploads") {
creates++;
stage = "uploading";
manifest = JSON.parse(bytes.toString()).manifest;
json({ datasetId: "fixture" });
} else if (req.url === "/api/v1/datasets/fixture") json({ state: stage });
} else if (
req.url === "/api/v1/contributions/00000000-0000-4000-8000-000000000024"
)
json({
remaining: 19,
playerRemaining: 12,
serverAddress: expectedServer,
bounds: { minX: -32, minZ: -32, maxX: 32, maxZ: 32 },
});
else if (
req.url ===
"/api/v1/contributions/00000000-0000-4000-8000-000000000024/server"
)
json({ serverAddress: expectedServer });
else if (req.url === "/api/v1/datasets/fixture") json({ state: stage });
else if (req.url === "/api/v1/uploads/sign")
json({
assets: manifest.assets.map((a: any) => ({
@@ -85,7 +101,7 @@ const api = createServer(async (req, res) => {
await new Promise<void>((r) => api.listen(0, "127.0.0.1", r));
await writeFile(
`${directory}/plugins/MineGeo/config.yml`,
`website: 'http://127.0.0.1:${(api.address() as any).port}'\ntoken: 'fixture-token'\nserver-name: 'Regression world'\nchunks-per-tick: 2\nviewpoints: 5\nmax-area-size: 2048\n`,
`website: 'http://127.0.0.1:${(api.address() as any).port}'\ntoken: 'fixture-token'\nserver-name: 'Regression world'\nserver-address: 'play.regression.example.com'\nchunks-per-tick: 2\nviewpoints: 24\nmax-area-size: 2048\n`,
);
const child = spawn("java", ["-Xmx1536M", "-jar", "paper.jar", "--nogui"], {
cwd: directory,
@@ -163,14 +179,15 @@ try {
child.stdin.write("forceload add -32 -32 31 31\n");
await new Promise((r) => setTimeout(r, 5000));
await command("minegeo export Regression World", /Export complete:/);
const relative = (
let relative = (
await readFile(`${directory}/plugins/MineGeo/latest-export.txt`, "utf8")
).trim();
const exportDir = `${directory}/plugins/MineGeo/${relative}`;
const local = datasetSchema.parse(
JSON.parse(await readFile(`${exportDir}/manifest.json`, "utf8")),
);
assert.equal(local.viewpoints.length, 5);
assert.equal(local.viewpoints.length, 24);
assert.equal(local.serverAddress, "play.regression.example.com");
const terrain = JSON.parse(
gunzipSync(await readFile(`${exportDir}/terrain.json.gz`)).toString(),
);
@@ -188,6 +205,51 @@ try {
assert.equal(heads, 1);
await command("minegeo upload", /Upload complete\. Open/);
assert.equal(finalizes, 1);
received = Buffer.alloc(0);
expectedServer = "wrong.example.com";
await command(
"minegeo contribute 00000000-0000-4000-8000-000000000024",
/Wrong capture server/,
);
assert.equal(creates, 1, "Mismatch must stop before creating a draft");
expectedServer = "PLAY.REGRESSION.EXAMPLE.COM.:25565";
await command(
"minegeo contribute 00000000-0000-4000-8000-000000000024",
/Upload complete\. Open/,
);
assert.equal(manifest.contributionTo, "00000000-0000-4000-8000-000000000024");
assert.equal(manifest.viewpoints.length, 12);
assert.equal(creates, 2);
expectedServer = "wrong.example.com";
await command(
"minegeo contribute 00000000-0000-4000-8000-000000000024",
/Wrong capture server/,
);
assert.equal(creates, 2, "A cached selection must recheck the server");
expectedServer = null;
await command(
"minegeo contribute 00000000-0000-4000-8000-000000000024",
/Upload complete\. Open/,
);
assert.equal(creates, 2, "Cleared server permits an idempotent retry");
assert.equal(finalizes, 2);
await command(
"minegeo contribute 00000000-0000-4000-8000-000000000024",
/Upload complete\. Open/,
);
assert.equal(creates, 2);
await command("minegeo export Random Positions", /Export complete:/);
relative = (
await readFile(`${directory}/plugins/MineGeo/latest-export.txt`, "utf8")
).trim();
const repeated = JSON.parse(
await readFile(
`${directory}/plugins/MineGeo/${relative}/manifest.json`,
"utf8",
),
);
assert.equal(repeated.viewpoints.length, 24);
assert.notDeepEqual(repeated.viewpoints, local.viewpoints);
await command("minegeo area world -256 -256 256 256", /area selected/);
const cancelled = wait(/Cancelled\. Completed exports are kept/);
child.stdin.write("minegeo export Cancel Test\nminegeo cancel\n");
@@ -211,6 +273,10 @@ try {
"TUS interruption and byte-perfect resume",
"repeated upload is idempotent",
"cancellation preserves completed export",
"24 random positions change on the next export",
"contribution command caps at 12 and retries idempotently",
"wrong server blocked before upload, including cached retry",
"owner override/default port and cleared address supported",
],
blocks: terrain.blocks.length,
chunks: terrain.coverage.length,