Skip to main content

rpfm_lib/
lib.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11//! Core library for reading and writing Total War game files.
12//!
13//! This crate provides comprehensive support for reading, writing, and manipulating file formats
14//! used by Creative Assembly in Total War games since Empire: Total War. It forms the foundation
15//! of the Rusted PackFile Manager (RPFM) project.
16//!
17//! # Supported Games
18//!
19//! - Total War: Pharaoh - Dynasties
20//! - Total War: Pharaoh
21//! - Total War: Warhammer 3
22//! - Total War Saga: Troy
23//! - Total War: Three Kingdoms
24//! - Total War: Warhammer 2
25//! - Total War: Warhammer
26//! - Total War Saga: Thrones of Britannia
27//! - Total War: Attila
28//! - Total War: Rome 2
29//! - Total War: Shogun 2
30//! - Total War: Napoleon
31//! - Total War: Empire
32//!
33//! # Supported File Formats
34//!
35//! The library supports 30+ file types including:
36//!
37//! - **Pack Files** (`.pack`): Container format for all game assets
38//! - **Database Tables** (`db/`): Game data with versioned schemas
39//! - **Localisation Files** (`.loc`): Translated text strings
40//! - **3D Models** (`.rigid_model_v2`): Unit and building meshes
41//! - **Animations**: AnimPack, AnimFragment, AnimsTable, MatchedCombat
42//! - **Audio**: Sound banks (`.bnk`), sound events, DAT containers
43//! - **Images**: DDS textures, atlases
44//! - **Maps**: BMD (battle map data), tile databases, vegetation
45//! - **Campaign**: ESF (save files), startpos
46//! - **UI**: UIC components, portrait settings, fonts
47//! - **Scripts**: Lua, XML, and other text formats
48//!
49//! See the [`files`] module for detailed information on each file type and its support level.
50//!
51//! # Architecture
52//!
53//! The library is organized into several key modules:
54//!
55//! - [`files`]: File format parsers and writers (30+ types)
56//! - [`schema`]: Database table schema definitions and versioning
57//! - [`binary`]: Low-level binary I/O utilities
58//! - [`games`]: Game-specific configuration and version detection
59//! - [`compression`]: LZ4, ZStd, and LZMA compression support
60//! - [`encryption`]: Pack file encryption/decryption
61//! - [`error`]: Error types and result handling
62//! - [`integrations`]: Optional Assembly Kit and Git integration
63//!
64//! # Feature Flags
65//!
66//! - `integration_assembly_kit`: Enable Assembly Kit raw table parsing
67//! - `integration_git`: Enable Git repository operations
68//!
69//! # Examples
70//!
71//! ## Reading a Pack File
72//!
73//! ```ignore
74//! use rpfm_lib::files::pack::Pack;
75//! use rpfm_lib::games::supported_games::{SupportedGames, KEY_WARHAMMER_3};
76//! use std::path::PathBuf;
77//!
78//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
79//! let path = PathBuf::from("path/to/pack.pack");
80//! let games = SupportedGames::default();
81//! let game_info = games.game(&KEY_WARHAMMER_3).unwrap();
82//! let pack = Pack::read_and_merge(&[path], game_info, true, false, false)?;
83//!
84//! for file in pack.files().values() {
85//!     println!("{}", file.path_in_container_raw());
86//! }
87//! # Ok(())
88//! # }
89//! ```
90//!
91//! ## Working with Database Tables
92//!
93//! ```ignore
94//! use rpfm_lib::files::{db::DB, Decodeable, DecodeableExtraData, RFile, RFileDecoded};
95//! use rpfm_lib::schema::Schema;
96//! use std::path::Path;
97//!
98//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
99//! let schema_path = Path::new("path/to/schema.ron");
100//! let schema = Schema::load(&schema_path, None)?;
101//! let mut extra_data = DecodeableExtraData::default();
102//! extra_data.set_schema(Some(&schema));
103//!
104//! // Decode a DB file (assuming pack is loaded)
105//! // let mut file = pack.files_by_path(&path, false).first().unwrap();
106//! // file.decode(&Some(extra_data), false, true)?;
107//! //
108//! // if let Ok(RFileDecoded::DB(db)) = file.decoded() {
109//! //     println!("Table {} has {} rows", db.table_name(), db.data().len());
110//! // }
111//! # Ok(())
112//! # }
113//! ```
114//!
115//! # Related Crates
116//!
117//! - `rpfm_extensions`: Higher-level features (dependencies, diagnostics, search, optimizer)
118//! - `rpfm_ui`: Qt-based desktop application
119
120// Disabled `Clippy` linters, with the reasons why they were disabled.
121#![allow(
122    clippy::too_many_arguments,             // Disabled because it gets annoying really quick.
123    clippy::field_reassign_with_default,    // Disabled because it gets annoying on tests.
124    clippy::assigning_clones,
125    clippy::type_complexity,
126    clippy::upper_case_acronyms,
127)]
128
129use regex::Regex;
130
131use std::sync::LazyLock;
132
133pub mod binary;
134pub mod compression;
135pub mod encryption;
136pub mod error;
137pub mod files;
138pub mod games;
139pub mod integrations;
140pub mod notes;
141pub mod schema;
142pub mod utils;
143
144#[cfg(test)] mod utils_test;
145
146/// Regular expression to identify database table file paths.
147///
148/// Matches paths in the format: `db/{table_name}_tables/{file}`
149///
150/// # Examples
151///
152/// - `db/units_tables/core_units.bin` → matches
153/// - `db/buildings_tables/data.bin` → matches
154/// - `data/units.txt` → does not match
155pub static REGEX_DB: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"db/[^/]+_tables/[^/]+$").unwrap());
156
157/// Regular expression to identify portrait settings file paths.
158///
159/// Matches any path ending with `portrait_settings` followed by optional characters and `.bin`.
160///
161/// # Examples
162///
163/// - `portraits/portrait_settings.bin` → matches
164/// - `data/portrait_settings_v2.bin` → matches
165/// - `other/settings.bin` → does not match
166pub static REGEX_PORTRAIT_SETTINGS: LazyLock<Regex> = LazyLock::new(|| Regex::new(r".*portrait_settings\S*\.bin$").unwrap());