This code automates the extraction of specific files, such as map files and screenshots, from Quake 3 PAK archives. It uses the node-stream-zip
library to read the archives and extracts the desired files to specific locations.
npm run import -- "find only bsps in map paks"
var StreamZip = require('node-stream-zip');
var fs = require('fs');
var path = require('path');
var importer = require('../Core');
var {listInProject} = importer.import("list project files")
function readPak(zipFile, cb) {
const zip = new StreamZip({
file: zipFile,
storeEntries: true
});
zip.on('ready', () => {
console.log('Entries read: ' + zip.entriesCount + ' ' + path.basename(zipFile));
for (const entry of Object.values(zip.entries())) {
if(entry.name.includes('.bsp')) {
console.log(entry.name)
/*var pk3Path = '/Applications/ioquake3/bestmaps/' + path.basename(pk3.name);
if(!fs.existsSync(pk3Path)) {
zip.extract(pk3.name, pk3Path, err => {
console.log((err ? 'Extract error ' : 'Extracted ') + pk3.name);
zip.close();
cb(zipFile);
});
return;
}*/
}
if(entry.name.includes('levelshots/') && entry.name !== 'levelshots/') {
var levelPath = '/Applications/ioquake3/bestmaps/levelshots/' + path.basename(entry.name)
if(!fs.existsSync(levelPath)) {
zip.extract(entry.name, levelPath, err => {
console.log((err ? 'Extract error ' : 'Extracted ') + entry.name);
zip.close();
cb(zipFile);
});
return;
}
}
}
zip.close()
cb();
});
zip.on('error', err => { cb() });
}
function extractPaks() {
var results = listInProject('/Applications/ioquake3/bestmaps', '**/*.pk3')
console.log(results)
return importer.runAllPromises(results.map(r => {
return (resolve) => {
try {
readPak(r, resolve)
} catch (e) {
if(e.message.includes('Bad archive')) {}
else { console.log(e) }
resolve()
}
}
})).then(results => results.filter(r => r))
}
module.exports = extractPaks;
const { promises: fsPromises } = require('fs');
const path = require('path');
const { listInProject } = require('../Core');
const StreamZip = require('node-stream-zip');
/**
* Function to read a pak file.
*
* @param {string} zipFile - The path to the zip file.
* @param {function} cb - The callback function to call when the operation is complete.
*/
async function readPak(zipFile) {
try {
const zip = new StreamZip({
file: zipFile,
storeEntries: true
});
await new Promise((resolve, reject) => {
zip.on('ready', () => {
resolve();
});
zip.on('error', (err) => {
reject(err);
});
});
console.log(`Entries read: ${zip.entriesCount} ${path.basename(zipFile)}`);
const entries = Object.values(zip.entries());
for (const entry of entries) {
if (entry.name.includes('.bsp')) {
console.log(entry.name);
}
if (entry.name.includes('levelshots/') && entry.name!== 'levelshots/') {
const levelPath = path.join('/Applications/ioquake3/bestmaps', 'levelshots', path.basename(entry.name));
if (!fsPromises.existsSync(levelPath)) {
zip.extract(entry.name, levelPath);
}
}
}
await new Promise((resolve) => {
zip.on('close', () => {
resolve();
});
});
} catch (err) {
console.log(err);
} finally {
return zipFile;
}
}
/**
* Function to extract paks.
*
* @returns {Promise<string[]>} A promise that resolves with an array of extracted pak files.
*/
async function extractPaks() {
const results = await listInProject('/Applications/ioquake3/bestmaps', '**/*.pk3');
const extracted = await Promise.all(results.map(async (r) => {
try {
await readPak(r);
return true;
} catch (e) {
if (e.message.includes('Bad archive')) {
return false;
} else {
console.log(e);
return true;
}
}
}));
return results.filter((_, index) => extracted[index]);
}
module.exports = extractPaks;
This code snippet is designed to extract files from Quake 3 PAK (package) archives.
Here's a breakdown:
Dependencies:
node-stream-zip
: A library for reading and extracting ZIP archives.fs
: Node.js file system module for interacting with files and directories.path
: Node.js path module for working with file paths.importer
: A custom module likely containing functions for interacting with the project structure.readPak
Function:
zipFile
) and a callback function (cb
) as input.StreamZip
object to read the PAK archive..bsp
(map) files and levelshots/
directory contents to specific locations.cb
) when extraction is complete.extractPaks
Function:
importer.listInProject
function to find all .pk3
files in the specified directory (/Applications/ioquake3/bestmaps
).readPak
.importer.runAllPromises
to execute all the promises concurrently.In essence, this code automates the process of extracting specific files from Quake 3 PAK archives, likely for use in a map editing or modding tool.