Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ata4/bspsrc/llms.txt

Use this file to discover all available pages before exploring further.

BSP files can contain embedded files in an internal ZIP archive called the pakfile. BSPSource can extract these files with optional smart filtering to exclude VBSP-generated content.

Understanding Pakfiles

The pakfile is a ZIP archive embedded in the BSP’s LUMP_PAKFILE lump. It typically contains:
  • Custom materials (.vmt, .vtf)
  • Custom models (.mdl, .vvd, .vtx, .phy)
  • Custom sounds (.wav, .mp3)
  • Particle manifests
  • VBSP-generated files (cubemaps, lighting data)

Basic Extraction

Extract All Files

config.unpackEmbedded = true;
config.smartUnpack = false; // Extract everything
This extracts the entire pakfile contents to the output directory.

Direct Pakfile Extraction

You can also extract the raw pakfile ZIP:
PakFile pakFile = new PakFile(bspFile);
pakFile.unpack(outputPath, true); // Direct ZIP extraction

Smart Unpacking

Smart unpacking filters out files automatically generated by VBSP, keeping only custom content:
config.unpackEmbedded = true;
config.smartUnpack = true; // Default: filter VBSP files

VBSP-Generated Files

BSPSource automatically detects and excludes these patterns: VHV Files (HDR lighting data):
sp_0.vhv
sp_1.vhv
sp_hdr_0.vhv
sp_hdr_1.vhv
Cubemap VTF Files:
c-64_128_256.vtf
c-64_128_256.hdr.vtf
Default Cubemaps:
cubemapdefault.vtf
cubemapdefault.hdr.vtf
Smart unpacking uses regex patterns to identify VBSP-generated files, preserving only mapper-created custom content.

Custom File Filtering

You can provide custom extraction filters:
PakFile pakFile = new PakFile(bspFile);

// Extract only materials
pakFile.unpack(outputPath, fileName -> 
    fileName.endsWith(".vmt") || fileName.endsWith(".vtf")
);

// Extract only models
pakFile.unpack(outputPath, fileName -> 
    fileName.endsWith(".mdl") || 
    fileName.endsWith(".vvd") || 
    fileName.endsWith(".vtx") || 
    fileName.endsWith(".phy")
);

// Exclude specific directories
pakFile.unpack(outputPath, fileName -> 
    !fileName.startsWith("maps/")
);

Extraction Features

Path Traversal Protection

BSPSource prevents malicious pakfiles from writing outside the extraction directory:
// Blocked: ../../../etc/passwd
// Allowed: materials/custom/wall.vtf
Files attempting path traversal are automatically skipped with warnings.

Invalid Path Handling

Files with invalid characters in their paths are skipped:
// Skipped: "file\x00name.txt" (contains null byte)

Duplicate File Protection

Existing files are never overwritten:
// If materials/wall.vtf exists, extraction is skipped

LZMA Compression Support

BSPSource supports LZMA-compressed pakfile entries (used in some Source 2007+ games):
  • Automatic LZMA detection
  • Proper decompression with EOS marker handling
  • Fallback for unsupported compression methods

Detection Functions

You can check if a file is VBSP-generated:
boolean isGenerated = PakFile.isVBSPGeneratedFile("c-64_128_256.vtf");
// Returns: true

boolean isGenerated = PakFile.isVBSPGeneratedFile("materials/custom/wall.vtf");
// Returns: false
Detection patterns:
// VHV pattern: sp(_hdr)?_\d+\.vhv
Pattern.compile("sp(_hdr)?_\\d+\\.vhv")

// Cubemap pattern: c(-?\d+)_(-?\d+)_(-?\d+)(\.hdr)?\.vtf
Pattern.compile("c(-?\\d+)_(-?\\d+)_(-?\\d+)(\\.hdr)?\\.vtf")

// Exact matches:
// - cubemapdefault.vtf
// - cubemapdefault.hdr.vtf

Configuration Examples

Extract Custom Content Only

BspSourceConfig config = new BspSourceConfig();
config.unpackEmbedded = true;
config.smartUnpack = true; // Filter out VBSP files

Extract Everything

BspSourceConfig config = new BspSourceConfig();
config.unpackEmbedded = true;
config.smartUnpack = false; // Include VBSP files

No Extraction

BspSourceConfig config = new BspSourceConfig();
config.unpackEmbedded = false;

Pakfile Structure

Typical pakfile contents:
pakfile.zip
├── materials/
│   ├── custom/
│   │   ├── wall.vmt
│   │   └── wall.vtf
│   └── maps/
│       └── mapname/
│           ├── c-64_128_256.vtf (VBSP)
│           └── cubemapdefault.vtf (VBSP)
├── models/
│   └── props/
│       ├── custom.mdl
│       ├── custom.vvd
│       └── custom.vtx
├── sound/
│   └── custom/
│       └── sound.wav
└── sp_0.vhv (VBSP)
With smartUnpack = true, only the custom files are extracted (excluding VBSP-generated files).

Error Handling

Missing Pakfile

try (ZipFile zip = pakFile.getZipFile()) {
    // Extract files
} catch (IOException ex) {
    // Pakfile broken or missing
}

Unsupported Compression

Files with unsupported compression methods are logged:
Cannot extract unsupported: file.txt| method: IMPLODE(6)| encryption: false

Invalid Entry Names

Skipped invalid_chars\x00.txt (contains invalid characters)

Working with Extracted Files

After extraction, custom content is organized by type:
output/
├── materials/
│   └── custom/
├── models/
│   └── props/
└── sound/
    └── custom/
You can then:
  1. Copy to your game’s directory structure
  2. Package into a custom content pack
  3. Include in a recompiled map

Advanced Usage

Extract Specific File Types

PakFile pakFile = new PakFile(bspFile);

// Materials only
pakFile.unpack(materialsPath, name -> 
    (name.endsWith(".vmt") || name.endsWith(".vtf")) &&
    !PakFile.isVBSPGeneratedFile(name)
);

// Models only
pakFile.unpack(modelsPath, name -> 
    name.startsWith("models/") &&
    (name.endsWith(".mdl") || name.endsWith(".vvd") || 
     name.endsWith(".vtx") || name.endsWith(".phy"))
);

Get ZipFile for Manual Processing

PakFile pakFile = new PakFile(bspFile);

try (ZipFile zip = pakFile.getZipFile()) {
    for (Enumeration<ZipArchiveEntry> e = zip.getEntries(); e.hasMoreElements();) {
        ZipArchiveEntry entry = e.nextElement();
        // Custom processing
    }
}
Some protected maps may include encrypted entity data (entities.dat) in the pakfile. See Protection Detection for details.

Build docs developers (and LLMs) love