Skip to main content

rpfm_lib/files/tile_database/
mod.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//! Tile database files for Total War terrain systems.
12//!
13//! The tile database (`tile_database.bin`) contains definitions for terrain tiles,
14//! including their rendering parameters, textures, climate variations, and linking rules.
15//! This data is used by the game's terrain system to generate and render battle maps.
16//!
17//! # File Format
18//!
19//! Tile database files use the FASTBIN0 binary format with versioned serialisation.
20//! Currently only version 1 is supported.
21//!
22//! # Structure
23//!
24//! The database contains several interconnected components:
25//! - **Render Parameters**: Global rendering settings for terrain.
26//! - **Conversion Parameters**: Parameters for tile format conversion.
27//! - **Climates**: Climate-specific tile variations (e.g., temperate, desert).
28//! - **Tile Sets**: Groups of related tiles.
29//! - **Tiles**: Individual terrain tile definitions with textures and properties.
30
31use getset::*;
32use serde_derive::{Serialize, Deserialize};
33
34use crate::binary::{ReadBytes, WriteBytes};
35use crate::error::{Result, RLibError};
36use crate::files::{Decodeable, EncodeableExtraData, Encodeable};
37use crate::utils::check_size_mismatch;
38
39use self::climate::Climate;
40use self::conversion_params::ConversionParams;
41use self::render_params::RenderParams;
42use self::tile_set::TileSet;
43use self::tile::Tile;
44
45use super::DecodeableExtraData;
46
47/// Name of the file used by Tile Databases.
48pub const NAME: &str = "tile_database.bin";
49
50/// FASTBIN0
51pub const SIGNATURE: &[u8; 8] = &[0x46, 0x41, 0x53, 0x54, 0x42, 0x49, 0x4E, 0x30];
52
53#[cfg(test)] mod tile_database_test;
54
55mod climate;
56mod conversion_params;
57mod render_params;
58mod texture;
59mod tile_set;
60mod tile;
61mod tile_link;
62mod tile_link_target;
63mod tile_variation;
64
65mod v1;
66
67//---------------------------------------------------------------------------//
68//                              Enum & Structs
69//---------------------------------------------------------------------------//
70
71/// In-memory representation of a decoded tile database file.
72///
73/// Contains all terrain tile definitions and related configuration data
74/// used by the game's terrain system.
75///
76/// # Fields
77///
78/// * `serialise_version` - Format version (currently only 1 is supported).
79/// * `render_params` - Global rendering parameters for terrain tiles.
80/// * `conversion_params` - Parameters for tile format conversion.
81/// * `climates` - Climate-specific tile configurations.
82/// * `tile_sets` - Groups of related tiles.
83/// * `tiles` - Individual tile definitions.
84#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
85#[getset(get = "pub", get_mut = "pub", set = "pub")]
86pub struct TileDatabase {
87    /// Serialisation format version.
88    serialise_version: u16,
89
90    /// Global rendering parameters.
91    render_params: RenderParams,
92    /// Tile conversion parameters.
93    conversion_params: ConversionParams,
94    /// Climate definitions with tile variations.
95    climates: Vec<Climate>,
96    /// Tile set groupings.
97    tile_sets: Vec<TileSet>,
98    /// Individual tile definitions.
99    tiles: Vec<Tile>,
100}
101
102
103//---------------------------------------------------------------------------//
104//                           Implementation of TileDatabase
105//---------------------------------------------------------------------------//
106
107
108impl Decodeable for TileDatabase {
109
110    fn decode<R: ReadBytes>(data: &mut R, extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
111        let signature_bytes = data.read_slice(8, false)?;
112        if signature_bytes.as_slice() != SIGNATURE {
113            return Err(RLibError::DecodingFastBinUnsupportedSignature(signature_bytes));
114        }
115
116        let mut fastbin = Self::default();
117        fastbin.serialise_version = data.read_u16()?;
118
119        match fastbin.serialise_version {
120            1 => fastbin.read_v1(data, extra_data)?,
121            _ => return Err(RLibError::DecodingFastBinUnsupportedVersion(String::from("TileDatabase"), fastbin.serialise_version)),
122        }
123
124        // If we are not in the last byte, it means we didn't parse the entire file, which means this file is corrupt.
125        check_size_mismatch(data.stream_position()? as usize, data.len()? as usize)?;
126
127        Ok(fastbin)
128    }
129}
130
131impl Encodeable for TileDatabase {
132
133    fn encode<W: WriteBytes>(&mut self, buffer: &mut W, extra_data: &Option<EncodeableExtraData>) -> Result<()> {
134        buffer.write_all(SIGNATURE)?;
135        buffer.write_u16(self.serialise_version)?;
136
137        match self.serialise_version {
138            1 => self.write_v1(buffer, extra_data)?,
139            _ => return Err(RLibError::EncodingFastBinUnsupportedVersion(String::from("TileDatabase"), self.serialise_version)),
140        }
141
142        Ok(())    }
143}