A Rust implementation of unp4k - a tool for extracting and modifying Star Citizen .p4k files.
Note
The functionality to modify/create P4K is experimental; it is only used for testing local tools and cannot be verified by the game.
This project is organized as a Cargo workspace:
unp4k_rs/
├── src/ # Core library (unp4k)
│ ├── lib.rs
│ ├── p4k.rs # P4K archive reading
│ ├── p4k_writer.rs # P4K archive writing
│ ├── cryxml.rs # CryXML format conversion
│ ├── dataforge/ # DataForge/DCB format parser
│ └── ...
└── crates/
├── unp4k-cli/ # Command-line tool (unp4k-cli)
│ └── src/main.rs
└── dataforge-mcp/ # MCP server for DataForge (optional)
└── src/
├── lib.rs
├── server.rs # HTTP server with Streamable HTTP transport
└── tools.rs # MCP tool definitions
# Install CLI tool
cargo install --git https://github.com/StarCitizenToolBox/unp4k_rs.git unp4k-cligit clone https://github.com/StarCitizenToolBox/unp4k_rs.git
cd unp4k_rs
cargo install --path crates/unp4k-cliunp4k --help- 📦 Open and extract Star Citizen
.p4karchives - ✏️ Create, modify and patch
.p4karchives - 🔐 AES-128-CBC encryption/decryption support
- 🗜️ Support for STORE, DEFLATE, and ZSTD compression
- 📝 CryXML binary format to standard XML conversion
- 📊 DataForge/DCB binary format to XML conversion
- 🔍 Full-text search across DCB records
- 💻 Cross-platform (Windows, macOS, Linux)
# Extract all files
unp4k Data.p4k
# Extract files matching a pattern
unp4k Data.p4k "*.xml"
unp4k Data.p4k "Data/Libs/*"# List all files
unp4k list Data.p4k
# List files matching a pattern
unp4k list Data.p4k "*.dcb"# Extract to current directory
unp4k extract Data.p4k
# Extract with pattern
unp4k extract Data.p4k "*.xml" -o ./output
# Extract and convert CryXML to standard XML
unp4k extract Data.p4k "*.xml" --convert-xmlunp4k info Data.p4k# Create a new P4K from a directory
unp4k pack output.p4k ./my_files
# With custom compression
unp4k pack output.p4k ./my_files -c zstd
unp4k pack output.p4k ./my_files -c deflate
unp4k pack output.p4k ./my_files -c store
# Without encryption
unp4k pack output.p4k ./my_files -e false
# With base path prefix
unp4k pack output.p4k ./my_files -b Data/MyMod# Patch a P4K with files from a directory
# Files in patch directory will replace matching files in the P4K
unp4k patch Data.p4k ./patches
# With base path prefix
unp4k patch Data.p4k ./patches -b Data/Localization# Add a file to the archive
unp4k add Data.p4k myfile.xml
# Add with custom archive path
unp4k add Data.p4k myfile.xml -a Data/Config/myfile.xml# Replace a file in the archive (keeps original compression settings)
unp4k replace Data.p4k myfile.xml Data/Config/myfile.xml# Delete files matching patterns
unp4k delete Data.p4k "*.tmp" "*.bak"# Show DCB file info
unp4k dcb Game.dcb --info
# Convert to separate XML files (like upstream unp4k)
unp4k dcb Game.dcb
# Convert to a single merged XML file
unp4k dcb Game.dcb --merge
# Specify output directory
unp4k dcb Game.dcb -o ./outputThe MCP (Model Context Protocol) server allows AI assistants to query and search DataForge/DCB data:
# Start MCP server on default port (3721)
unp4k mcp Game.dcb
# Start on custom port
unp4k mcp Game.dcb -p 8080Available MCP Tools:
| Tool | Description |
|---|---|
get_stats |
Get DataForge statistics and metadata |
list_paths |
List record paths with keyword/regex filtering and pagination |
get_content |
Get XML content of a specific record |
batch_get_content |
Get XML content for multiple records (max 10) |
search_in_paths |
Two-level filtering: path keyword + content keyword |
full_text_search |
Search across all record paths and XML content |
suggest_paths |
Path auto-completion based on prefix |
list_directories |
Explore record hierarchy at different depths |
Note: DataForge files can contain 50000+ records (GB-level data). Always use
get_statsfirst to understand data size, and usecount_only=truewith pagination for large queries.
Add to your Cargo.toml:
[dependencies]
unp4k = { git = "https://github.com/StarCitizenToolBox/unp4k_rs.git" }use unp4k::{P4kFile, CryXmlReader};
fn main() -> anyhow::Result<()> {
// Open the archive
let mut p4k = P4kFile::open("Data.p4k")?;
// List entries
for entry in p4k.entries() {
println!("{}: {} bytes", entry.name, entry.uncompressed_size);
}
// Extract a file
let data = p4k.extract("Data/Libs/Config/defaultProfile.xml")?;
// Convert CryXML to standard XML
if CryXmlReader::is_cryxml(&data) {
let xml = CryXmlReader::parse(&data)?;
println!("{}", xml);
}
Ok(())
}use unp4k::{P4kWriter, P4kWriteEntry, P4kWriteOptions, P4kModifier, CompressionMethod};
fn create_archive() -> anyhow::Result<()> {
// Create a new P4K
let mut writer = P4kWriter::create("my_archive.p4k")?;
// Add entries
let entry = P4kWriteEntry::new("Data/test.xml", b"<root/>".to_vec());
writer.add_entry(entry)?;
// Or add from file
writer.add_file("local_file.txt", "Data/remote_file.txt")?;
writer.finish()?;
Ok(())
}
fn modify_archive() -> anyhow::Result<()> {
// Open existing P4K for modification
let mut modifier = P4kModifier::open("Data.p4k")?;
// Add/replace a file
modifier.add(P4kWriteEntry::new("Data/new_file.xml", b"<data/>".to_vec()));
// Delete a file
modifier.delete("Data/old_file.xml");
// Save to new file
modifier.save("Data_modified.p4k")?;
Ok(())
}use unp4k::dataforge::{DataForge, search_records};
fn main() -> anyhow::Result<()> {
let data = std::fs::read("Game.dcb")?;
let df = DataForge::parse(&data)?;
// List record paths
for path in df.record_paths().take(10) {
println!("{}", path);
}
// Convert a record to XML
let xml = df.record_to_xml("path/to/record", true)?;
println!("{}", xml);
// Full-text search across all records
let results = search_records(&df, "vehicle");
for result in results {
println!("Found in: {} ({} matches)", result.path, result.matches.len());
}
Ok(())
}The .p4k files are encrypted ZIP archives with custom features:
- Encryption: AES-128-CBC with a known public key (same as CryEngine)
- Compression Methods:
STORE(0) - No compressionDEFLATE(8) - Standard ZIP compressionZSTD(100) - Zstandard compression (custom extension)
- CryXML: Binary XML format used for many game configuration files
- Original unp4k by dolkensp
- Star Citizen by Cloud Imperium Games
GNU GENERAL PUBLIC LICENSE Version 3