/* * The Peacock Project - a HITMAN server replacement. * Copyright (C) 2021-2023 The Peacock Project Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import { existsSync } from "fs" import { join, basename, sep } from "path" import millis from "ms" import { mkdir, readdir, readFile, unlink, writeFile } from "fs/promises" import { createHash } from "crypto" import { Packr } from "msgpackr" import { brotliCompress } from "zlib" import { promisify } from "util" import glob from "fast-glob" import prettier from "prettier" const packer = new Packr({ bundleStrings: true, }) async function readJson(filePath) { return JSON.parse((await readFile(filePath)).toString()) } async function createResourcesFolder(resources) { if (!existsSync(resources)) { await mkdir(resources) } else { for (const prp of await readdir(resources)) { await unlink(join(resources, prp)) } } } async function handleFile(resources, name, contents) { const targetName = createHash("md5").update(name).digest("hex") await writeFile(join(resources, `${targetName}.prp`), packer.pack(contents)) } export async function generateRequireTable() { const files = glob.sync("**/*.ts", { cwd: "./components", ignore: [ "index.ts", "generatedPeacockRequireTable.ts", "types/globals.d.ts", ], }) const imports = [] const requiresTable = [] files.forEach((e) => { const variable = basename(e, ".ts") const importPath = e.replaceAll(sep, "/").replace(/\.ts$/, "") imports.push(`import * as ${variable} from "./${importPath}"`) requiresTable.push( `"@peacockproject/core/${importPath}": { __esModule: true, ...${variable}}`, ) }) const prettierConfig = await prettier.resolveConfig() prettierConfig.parser = "babel" const generatedPeacockRequireTableFile = prettier.format( `/* * The Peacock Project - a HITMAN server replacement. * Copyright (C) 2021-2023 The Peacock Project Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ ${imports.join("\n")} export default { ${requiresTable.join(",\n")} }`, prettierConfig, ) await writeFile( "components/generatedPeacockRequireTable.ts", generatedPeacockRequireTableFile, ) } export async function packResources() { const challengesResources = join("resources", "challenges") await createResourcesFolder(challengesResources) const masteryResources = join("resources", "mastery") await createResourcesFolder(masteryResources) const start = Date.now() const contracts = glob.sync("contractdata/**/*.json") const b = [] const el = [] for (const path of contracts) { const filename = basename(path) if ( [ "FREEDOMFIGHTERSLEGACY.json", "THELASTYARDBIRD_SCPC.json", ].includes(filename) ) { continue } if (filename.includes(".d.ts")) { return } const json = await readJson(path) if (filename.endsWith("_CHALLENGES.json")) { // _LOCATION_CHALLENGES.json await handleFile(challengesResources, filename + "#packed", json) continue } if (filename.endsWith("_MASTERY.json")) { // _LOCATION_MASTERY.json await handleFile(masteryResources, filename + "#packed", json) continue } // dev scope if (json.Metadata.PublicId?.startsWith("0")) { delete json.Metadata.PublicId } if (json.Metadata.LastUpdate) { delete json.Metadata.LastUpdate } if (json.Metadata.Release) { delete json.Metadata.Release } if (json.Metadata.ServerVersion) { delete json.Metadata.ServerVersion } if (json.Metadata.GameVersion) { delete json.Metadata.GameVersion } if (json.Metadata.CreationTimestamp) { delete json.Metadata.CreationTimestamp } if (json.Metadata.CodeName_Hint) { delete json.Metadata.CodeName_Hint } switch (json?.Metadata?.Type) { case "elusive": el.push(json) break default: b.push(json) } } const d = JSON.stringify({ b, el }) const compressed = await promisify(brotliCompress)(d) await writeFile("resources/contracts.br", compressed) console.log( `Gathered built-in contracts and challenges in ${millis( Date.now() - start, )}`, ) }