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}