valve-parsers


Namevalve-parsers JSON
Version 1.0.2 PyPI version JSON
download
home_pagehttps://github.com/cueki/valve-parsers
SummaryPython library for parsing Valve game files (VPK and PCF)
upload_time2025-07-29 06:53:44
maintainerNone
docs_urlNone
authorcueki
requires_python>=3.8
licenseMIT
keywords valve vpk pcf particle steam source engine team fortress tf2 half-life parser archive modding
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Valve Parsers

A Python library for parsing Valve game files, extracted from my casual-preloader project. This library provides support for:

- **VPK (Valve Package)** files - Valve's archive format used in Source engine games
- **PCF (Particle)** files - Valve's particle system files - **See constants.py for supported versions**

## Features

- Support for single-file and multi-file VPK archives (creation and modification)
- Full VPK directory parsing and file extraction
- In-place VPK file patching with size checking
- PCF parsing and encoding
- Support for all PCF attribute types (see constants.py for these as well)

## Installation

```bash
pip install valve-parsers
```

## Quick Start (Parsing + Modification)

### VPK Files

```python
from valve_parsers import VPKFile

# Open and parse a VPK file
vpk = VPKFile("path/to/archive.vpk").parse_directory()

# List all files
files = vpk.list_files()
print(f"Found {len(files)} files")

# Find specific files
texture_files = vpk.list_files(extension="vtf")
material_files = vpk.find_files("materials/*.vmt")

# Extract a file
vpk.extract_file("materials/models/player/scout.vmt", "output/scout.vmt")

# Get file information
entry_info = vpk.get_file_entry("scripts/game_sounds.txt")
if entry_info:
    extension, directory, entry = entry_info
    print(f"File size: {entry.entry_length} bytes")
    print(f"Archive index: {entry.archive_index}")
    
# Patch a file
# Read a new material file from disk
new_texture_path = "my_custom_material.vmt"
with open(new_texture_path, 'rb') as f:
    new_texture_data = f.read()

# Target file path inside the VPK
target_file = "materials/models/player/scout_red.vmt"

# Optionally create a backup before modification
vpk.patch_file(target_file, new_texture_data, create_backup=False)

```

### PCF Files

```python
from valve_parsers import PCFFile

# Open and decode a PCF file
pcf = PCFFile("path/to/particles.pcf").decode()

print(f"PCF Version: {pcf.version}")
print(f"String dictionary: {len(pcf.string_dictionary)} entries")
print(f"Elements: {len(pcf.elements)} particle systems")

# Print particle system data
for element in pcf.elements:
    print(f"Element: {element.element_name}")
    for attr_name, (attr_type, attr_value) in element.attributes.items():
        print(f"  {attr_name.decode()}: {attr_value}")
        
# Rename all operators to ''
for i, element in enumerate(pcf.elements):
    type_name = pcf.string_dictionary[element.type_name_index].decode('ascii')
    if type_name == 'DmeParticleOperator':
        element.element_name = str('').encode('ascii')

# Encode back to file
pcf.encode("output/modified_particles.pcf")
```

### Creating VPK Archives

```python
from valve_parsers import VPKFile

# Create a single-file VPK
success = VPKFile.create("source_directory", "output/archive.vpk")

# Create a multi-file VPK with size limit (100MB per archive spit)
success = VPKFile.create("source_directory", "output/archive", split_size=100*1024*1024)
```

## API Reference

### VPKFile

The main class for working with VPK archives.

#### Constructor
- `VPKFile(vpk_path: str)` - Initialize with path to VPK file

#### Methods
- `parse_directory() -> VPKFile` - Parse the VPK directory structure
- `list_files(extension: str = None, path: str = None) -> List[str]` - List files with optional filtering
- `find_files(pattern: str) -> List[str]` - Find files matching a glob pattern
- `find_file_path(filename: str) -> Optional[str]` - Find the full path of a filename
- `extract_file(filepath: str, output_path: str) -> bool` - Extract a file from the archive
- `patch_file(filepath: str, new_data: bytes, create_backup: bool = False) -> bool` - Modify a file in the archive
- `create(source_dir: str, output_base_path: str, split_size: int = None) -> bool` - Create new VPK archive

#### Properties
- `directory` - Parsed directory structure
- `is_dir_vpk` - Whether this is a directory VPK file
- `vpk_path` - Path to the VPK file

### VPKDirectoryEntry

Represents an entry in the VPK directory.

#### Properties
- `crc: int` - CRC32 checksum
- `preload_bytes: int` - Number of preload bytes
- `archive_index: int` - Archive file index
- `entry_offset: int` - Offset within archive
- `entry_length: int` - Length of file data
- `preload_data: Optional[bytes]` - Preloaded data

### PCFFile

The main class for working with PCF particle files.

#### Constructor
- `PCFFile(input_file: Union[Path, str], version: str = "DMX_BINARY2_PCF1")` - Initialize with file path, default version is "DMX_BINARY2_PCF1"

#### Methods
- `decode() -> PCFFile` - Parse the PCF file
- `encode(output_path: Union[Path, str]) -> PCFFile` - Write PCF file to disk

#### Properties
- `version` - PCF version string
- `string_dictionary` - List of strings used in the file
- `elements` - List of particle system elements

### PCFElement

Represents a particle system element.

#### Properties
- `type_name_index: int` - Index into string dictionary for type name
- `element_name: bytes` - Name of the element
- `data_signature: bytes` - 16-byte signature
- `attributes: Dict[bytes, Tuple[AttributeType, Any]]` - Element attributes

### Constants

- `PCFVersion` - Enum of supported PCF versions
- `AttributeType` - Enum of PCF attribute types

## Supported Games

This library works with VPK and PCF files from Orange Box titles. 
Mostly intended for TF2, YMMV with other games.

See: 

https://developer.valvesoftware.com/wiki/PCF 

https://developer.valvesoftware.com/wiki/VPK_(file_format)

## License

MIT License - See LICENSE file for details.

## Contributing

This library was extracted from my casual-pre-loader project. Contributions are welcome!

## Changelog
### 1.0.2
- Single file VPK no longer has _dir name
### 1.0.1
- Nothing
### 1.0.0
- Initial release
- VPK parsing and creation support
- PCF parsing and encoding support

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/cueki/valve-parsers",
    "name": "valve-parsers",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "valve, vpk, pcf, particle, steam, source engine, team fortress, tf2, half-life, parser, archive, modding",
    "author": "cueki",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/8f/b0/99731b2df499905b2871baad1c49265d41772233da8ef631e4d9ddafcbc8/valve_parsers-1.0.2.tar.gz",
    "platform": null,
    "description": "# Valve Parsers\n\nA Python library for parsing Valve game files, extracted from my casual-preloader project. This library provides support for:\n\n- **VPK (Valve Package)** files - Valve's archive format used in Source engine games\n- **PCF (Particle)** files - Valve's particle system files - **See constants.py for supported versions**\n\n## Features\n\n- Support for single-file and multi-file VPK archives (creation and modification)\n- Full VPK directory parsing and file extraction\n- In-place VPK file patching with size checking\n- PCF parsing and encoding\n- Support for all PCF attribute types (see constants.py for these as well)\n\n## Installation\n\n```bash\npip install valve-parsers\n```\n\n## Quick Start (Parsing + Modification)\n\n### VPK Files\n\n```python\nfrom valve_parsers import VPKFile\n\n# Open and parse a VPK file\nvpk = VPKFile(\"path/to/archive.vpk\").parse_directory()\n\n# List all files\nfiles = vpk.list_files()\nprint(f\"Found {len(files)} files\")\n\n# Find specific files\ntexture_files = vpk.list_files(extension=\"vtf\")\nmaterial_files = vpk.find_files(\"materials/*.vmt\")\n\n# Extract a file\nvpk.extract_file(\"materials/models/player/scout.vmt\", \"output/scout.vmt\")\n\n# Get file information\nentry_info = vpk.get_file_entry(\"scripts/game_sounds.txt\")\nif entry_info:\n    extension, directory, entry = entry_info\n    print(f\"File size: {entry.entry_length} bytes\")\n    print(f\"Archive index: {entry.archive_index}\")\n    \n# Patch a file\n# Read a new material file from disk\nnew_texture_path = \"my_custom_material.vmt\"\nwith open(new_texture_path, 'rb') as f:\n    new_texture_data = f.read()\n\n# Target file path inside the VPK\ntarget_file = \"materials/models/player/scout_red.vmt\"\n\n# Optionally create a backup before modification\nvpk.patch_file(target_file, new_texture_data, create_backup=False)\n\n```\n\n### PCF Files\n\n```python\nfrom valve_parsers import PCFFile\n\n# Open and decode a PCF file\npcf = PCFFile(\"path/to/particles.pcf\").decode()\n\nprint(f\"PCF Version: {pcf.version}\")\nprint(f\"String dictionary: {len(pcf.string_dictionary)} entries\")\nprint(f\"Elements: {len(pcf.elements)} particle systems\")\n\n# Print particle system data\nfor element in pcf.elements:\n    print(f\"Element: {element.element_name}\")\n    for attr_name, (attr_type, attr_value) in element.attributes.items():\n        print(f\"  {attr_name.decode()}: {attr_value}\")\n        \n# Rename all operators to ''\nfor i, element in enumerate(pcf.elements):\n    type_name = pcf.string_dictionary[element.type_name_index].decode('ascii')\n    if type_name == 'DmeParticleOperator':\n        element.element_name = str('').encode('ascii')\n\n# Encode back to file\npcf.encode(\"output/modified_particles.pcf\")\n```\n\n### Creating VPK Archives\n\n```python\nfrom valve_parsers import VPKFile\n\n# Create a single-file VPK\nsuccess = VPKFile.create(\"source_directory\", \"output/archive.vpk\")\n\n# Create a multi-file VPK with size limit (100MB per archive spit)\nsuccess = VPKFile.create(\"source_directory\", \"output/archive\", split_size=100*1024*1024)\n```\n\n## API Reference\n\n### VPKFile\n\nThe main class for working with VPK archives.\n\n#### Constructor\n- `VPKFile(vpk_path: str)` - Initialize with path to VPK file\n\n#### Methods\n- `parse_directory() -> VPKFile` - Parse the VPK directory structure\n- `list_files(extension: str = None, path: str = None) -> List[str]` - List files with optional filtering\n- `find_files(pattern: str) -> List[str]` - Find files matching a glob pattern\n- `find_file_path(filename: str) -> Optional[str]` - Find the full path of a filename\n- `extract_file(filepath: str, output_path: str) -> bool` - Extract a file from the archive\n- `patch_file(filepath: str, new_data: bytes, create_backup: bool = False) -> bool` - Modify a file in the archive\n- `create(source_dir: str, output_base_path: str, split_size: int = None) -> bool` - Create new VPK archive\n\n#### Properties\n- `directory` - Parsed directory structure\n- `is_dir_vpk` - Whether this is a directory VPK file\n- `vpk_path` - Path to the VPK file\n\n### VPKDirectoryEntry\n\nRepresents an entry in the VPK directory.\n\n#### Properties\n- `crc: int` - CRC32 checksum\n- `preload_bytes: int` - Number of preload bytes\n- `archive_index: int` - Archive file index\n- `entry_offset: int` - Offset within archive\n- `entry_length: int` - Length of file data\n- `preload_data: Optional[bytes]` - Preloaded data\n\n### PCFFile\n\nThe main class for working with PCF particle files.\n\n#### Constructor\n- `PCFFile(input_file: Union[Path, str], version: str = \"DMX_BINARY2_PCF1\")` - Initialize with file path, default version is \"DMX_BINARY2_PCF1\"\n\n#### Methods\n- `decode() -> PCFFile` - Parse the PCF file\n- `encode(output_path: Union[Path, str]) -> PCFFile` - Write PCF file to disk\n\n#### Properties\n- `version` - PCF version string\n- `string_dictionary` - List of strings used in the file\n- `elements` - List of particle system elements\n\n### PCFElement\n\nRepresents a particle system element.\n\n#### Properties\n- `type_name_index: int` - Index into string dictionary for type name\n- `element_name: bytes` - Name of the element\n- `data_signature: bytes` - 16-byte signature\n- `attributes: Dict[bytes, Tuple[AttributeType, Any]]` - Element attributes\n\n### Constants\n\n- `PCFVersion` - Enum of supported PCF versions\n- `AttributeType` - Enum of PCF attribute types\n\n## Supported Games\n\nThis library works with VPK and PCF files from Orange Box titles. \nMostly intended for TF2, YMMV with other games.\n\nSee: \n\nhttps://developer.valvesoftware.com/wiki/PCF \n\nhttps://developer.valvesoftware.com/wiki/VPK_(file_format)\n\n## License\n\nMIT License - See LICENSE file for details.\n\n## Contributing\n\nThis library was extracted from my casual-pre-loader project. Contributions are welcome!\n\n## Changelog\n### 1.0.2\n- Single file VPK no longer has _dir name\n### 1.0.1\n- Nothing\n### 1.0.0\n- Initial release\n- VPK parsing and creation support\n- PCF parsing and encoding support\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python library for parsing Valve game files (VPK and PCF)",
    "version": "1.0.2",
    "project_urls": {
        "Homepage": "https://github.com/cueki/valve-parsers",
        "Issues": "https://github.com/cueki/valve-parsers/issues",
        "Repository": "https://github.com/cueki/valve-parsers"
    },
    "split_keywords": [
        "valve",
        " vpk",
        " pcf",
        " particle",
        " steam",
        " source engine",
        " team fortress",
        " tf2",
        " half-life",
        " parser",
        " archive",
        " modding"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "de59ab2a4a7bf256f5f6f3449a0cbbdb9919b198d8eb591bf4a551976c0140fb",
                "md5": "4d0358db75ddaeca49d6e1711e46f50d",
                "sha256": "eae553a6f6a822c563ad7d381330775fd7afd92bddf8a1c1641fbae7a54fae5c"
            },
            "downloads": -1,
            "filename": "valve_parsers-1.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4d0358db75ddaeca49d6e1711e46f50d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 4471,
            "upload_time": "2025-07-29T06:53:43",
            "upload_time_iso_8601": "2025-07-29T06:53:43.703365Z",
            "url": "https://files.pythonhosted.org/packages/de/59/ab2a4a7bf256f5f6f3449a0cbbdb9919b198d8eb591bf4a551976c0140fb/valve_parsers-1.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8fb099731b2df499905b2871baad1c49265d41772233da8ef631e4d9ddafcbc8",
                "md5": "303800a0c4307ca420f11496b57ac3aa",
                "sha256": "8c5773e3ab1752228650e648ee1d1c45f5b2c04121e4cb5cc1a9f47e6301d278"
            },
            "downloads": -1,
            "filename": "valve_parsers-1.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "303800a0c4307ca420f11496b57ac3aa",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 4969,
            "upload_time": "2025-07-29T06:53:44",
            "upload_time_iso_8601": "2025-07-29T06:53:44.528644Z",
            "url": "https://files.pythonhosted.org/packages/8f/b0/99731b2df499905b2871baad1c49265d41772233da8ef631e4d9ddafcbc8/valve_parsers-1.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-29 06:53:44",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "cueki",
    "github_project": "valve-parsers",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "valve-parsers"
}
        
Elapsed time: 2.55961s