Files
PAKEntpacker/README.md
Markus Nellen-Schmitz a4649a40db initial commit
2026-02-20 22:56:57 +01:00

219 lines
5.0 KiB
Markdown

# Reforger PAK Unpacker (Node.js)
Node.js library to extract files from Arma Reforger `.pak` archive files.
## Features
- Extract all files from PAK archives
- Extract specific files by name
- List all files in an archive
- Support for Zlib compressed files
- Async and sync APIs
- Easy integration into Express.js or other Node.js applications
## Installation
```bash
npm install
```
## Usage
### Basic Example - Extract All Files
```javascript
const { PakUnpacker } = require('./PakUnpacker');
async function extractPak() {
const unpacker = new PakUnpacker('path/to/file.pak');
await unpacker.load();
console.log(`Found ${unpacker.entries.length} files`);
await unpacker.extract('./output');
console.log('Extraction complete!');
}
extractPak();
```
### List Files in Archive
```javascript
const { PakUnpacker } = require('./PakUnpacker');
async function listFiles() {
const unpacker = new PakUnpacker('path/to/file.pak');
await unpacker.load();
const files = unpacker.listFiles();
files.forEach(file => {
console.log(`${file.name} - ${file.size} bytes (${file.compressed ? 'Compressed' : 'Uncompressed'})`);
});
}
listFiles();
```
### Extract a Specific File
```javascript
const { PakUnpacker } = require('./PakUnpacker');
async function extractFile() {
const unpacker = new PakUnpacker('path/to/file.pak');
await unpacker.load();
const fileData = await unpacker.getFile('config.json');
if (fileData) {
console.log('File content:', fileData.toString('utf8'));
} else {
console.log('File not found');
}
}
extractFile();
```
### Synchronous API
```javascript
const { PakUnpacker } = require('./PakUnpacker');
function extractPakSync() {
const unpacker = new PakUnpacker('path/to/file.pak');
unpacker.loadSync();
console.log(`Found ${unpacker.entries.length} files`);
unpacker.extractSync('./output');
console.log('Extraction complete!');
}
extractPakSync();
```
## API Integration Example
### Express.js REST API
```javascript
const express = require('express');
const { PakUnpacker } = require('./PakUnpacker');
const app = express();
// List all files in a PAK archive
app.get('/api/pak/:pakName/files', async (req, res) => {
try {
const unpacker = new PakUnpacker(`./paks/${req.params.pakName}.pak`);
await unpacker.load();
const files = unpacker.listFiles();
res.json({ success: true, files });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
// Extract a specific file
app.get('/api/pak/:pakName/extract/:fileName(*)', async (req, res) => {
try {
const unpacker = new PakUnpacker(`./paks/${req.params.pakName}.pak`);
await unpacker.load();
const fileData = await unpacker.getFile(req.params.fileName);
if (fileData) {
res.setHeader('Content-Type', 'application/octet-stream');
res.send(fileData);
} else {
res.status(404).json({ success: false, error: 'File not found' });
}
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
```
## PAK File Format
Reforger PAK files have the following structure:
1. **FORM Block**: Header with size (Big Endian Int32)
2. **HEAD Block**: 32 bytes header data
3. **DATA Block**: Size + data block
4. **Entries Block**: Directory and file entries
### Entry Types
- **Type 0**: Directory (with child count)
- **Type 1**: File (with offset, size, original size, compression info)
### Compression
- **None** (0x00): No compression
- **Zlib** (0x106): Deflate compression with 2-byte Zlib header
## API Reference
### Class: PakUnpacker
#### Constructor
```javascript
new PakUnpacker(filePath)
```
- `filePath` (string): Path to the .pak file
#### Methods
##### async load()
Load and parse the PAK file asynchronously.
##### loadSync()
Load and parse the PAK file synchronously (blocking).
##### async extract(dstDir)
Extract all files to the destination directory.
- `dstDir` (string): Destination directory path
##### extractSync(dstDir)
Extract all files synchronously.
- `dstDir` (string): Destination directory path
##### async getFile(fileName)
Get a specific file's data by name.
- `fileName` (string): Name or partial name of the file
- Returns: `Promise<Buffer|null>`
##### getFileSync(fileName)
Get a specific file's data synchronously.
- `fileName` (string): Name or partial name of the file
- Returns: `Buffer|null`
##### listFiles()
List all files in the PAK archive.
- Returns: Array of objects with `{name, size, originalSize, compressed}` properties
#### Properties
- `entries` (Array): Array of PakEntryFile objects
- `formSize` (number): Size of the FORM block
- `dataSize` (number): Size of the DATA block
- `entriesSize` (number): Size of the entries block
## Requirements
- Node.js >= 14.0.0
- No external dependencies (uses built-in modules only)
## License
MIT
## Credits
Converted from the original C# implementation.