mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-01-19 12:14:47 +00:00
109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { parseArgs } from "node:util";
|
|
import ignore from "ignore";
|
|
import unzipper from "unzipper";
|
|
import { normalizePath } from "@/src/stringUtils";
|
|
import { walkDirectory } from "@/src/fileUtils";
|
|
|
|
const inputBaseDir = process.env.BASE_DIR || "GameData/base";
|
|
const outputBaseDir = "docs/base";
|
|
|
|
// NOTE! Yes, the files below will be ignored. But this also expects `inputBaseDir`
|
|
// to largely have already been pruned of files that are indistinguishable from
|
|
// useful files - like player skins, voice binds, and anything else that will
|
|
// not be used by the map tool. So, remove `voice.vl2` before running this, for
|
|
// example. Random scripts are typically fine, since they're small (and other
|
|
// scripts may expect them to be available).
|
|
const ignoreList = ignore().add(`
|
|
fonts/
|
|
lighting/
|
|
prefs/
|
|
.DS_Store
|
|
*.dso
|
|
*.gui
|
|
*.ico
|
|
*.ml
|
|
*.nav
|
|
*.txt
|
|
`);
|
|
|
|
async function extractAssets({ clean }: { clean: boolean }) {
|
|
const vl2Files: string[] = [];
|
|
const looseFiles: string[] = [];
|
|
|
|
// Discover all files
|
|
await walkDirectory(inputBaseDir, {
|
|
onFile: ({ entry }) => {
|
|
const filePath = path.join(entry.parentPath, entry.name);
|
|
const resourcePath = normalizePath(path.relative(inputBaseDir, filePath));
|
|
if (!ignoreList.ignores(resourcePath)) {
|
|
if (/\.vl2$/i.test(entry.name)) {
|
|
vl2Files.push(filePath);
|
|
} else {
|
|
looseFiles.push(filePath);
|
|
}
|
|
}
|
|
},
|
|
onDir: ({ entry }) => {
|
|
const dirPath = path.join(entry.parentPath, entry.name);
|
|
const resourcePath =
|
|
normalizePath(path.relative(inputBaseDir, dirPath)) + "/";
|
|
const shouldRecurse = !ignoreList.ignores(resourcePath);
|
|
return shouldRecurse;
|
|
},
|
|
});
|
|
|
|
if (clean) {
|
|
console.log(`Cleaning ${outputBaseDir}…`);
|
|
await fs.rm(outputBaseDir, { recursive: true, force: true });
|
|
}
|
|
|
|
await fs.mkdir(outputBaseDir, { recursive: true });
|
|
|
|
for (const filePath of looseFiles) {
|
|
const relativePath = path.relative(inputBaseDir, filePath);
|
|
const outFile = path.join(outputBaseDir, relativePath);
|
|
const outDir = path.dirname(outFile);
|
|
|
|
console.log(outFile);
|
|
await fs.mkdir(outDir, { recursive: true });
|
|
await fs.copyFile(filePath, outFile);
|
|
}
|
|
|
|
// Extract .vl2 files
|
|
for (const archivePath of vl2Files) {
|
|
const relativePath = path.relative(inputBaseDir, archivePath);
|
|
const archive = await unzipper.Open.file(archivePath);
|
|
const outputArchiveDir = path.join(outputBaseDir, "@vl2", relativePath);
|
|
|
|
for (const entry of archive.files) {
|
|
if (entry.type === "Directory") continue;
|
|
|
|
const resourcePath = normalizePath(entry.path);
|
|
if (ignoreList.ignores(resourcePath)) continue;
|
|
|
|
const outFile = path.join(outputArchiveDir, resourcePath);
|
|
const outDir = path.dirname(outFile);
|
|
|
|
console.log(outFile);
|
|
await fs.mkdir(outDir, { recursive: true });
|
|
const content = await entry.buffer();
|
|
await fs.writeFile(outFile, content);
|
|
}
|
|
}
|
|
|
|
console.log("Done.");
|
|
}
|
|
|
|
const { values } = parseArgs({
|
|
options: {
|
|
clean: {
|
|
type: "boolean",
|
|
default: false,
|
|
},
|
|
},
|
|
});
|
|
|
|
extractAssets({ clean: values.clean });
|