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 assembly_kit;
56mod climate;
57mod conversion_params;
58mod render_params;
59mod texture;
60mod tile_set;
61mod tile;
62mod tile_link;
63mod tile_link_target;
64mod tile_variation;
65
66mod v1;
67
68//---------------------------------------------------------------------------//
69// Enum & Structs
70//---------------------------------------------------------------------------//
71
72/// In-memory representation of a decoded tile database file.
73///
74/// Contains all terrain tile definitions and related configuration data
75/// used by the game's terrain system.
76///
77/// # Fields
78///
79/// * `serialise_version` - Format version (currently only 1 is supported).
80/// * `render_params` - Global rendering parameters for terrain tiles.
81/// * `conversion_params` - Parameters for tile format conversion.
82/// * `climates` - Climate-specific tile configurations.
83/// * `tile_sets` - Groups of related tiles.
84/// * `tiles` - Individual tile definitions.
85#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
86#[getset(get = "pub", get_mut = "pub", set = "pub")]
87pub struct TileDatabase {
88 /// Serialisation format version.
89 serialise_version: u16,
90
91 /// Global rendering parameters.
92 render_params: RenderParams,
93 /// Tile conversion parameters.
94 conversion_params: ConversionParams,
95 /// Climate definitions with tile variations.
96 climates: Vec<Climate>,
97 /// Tile set groupings.
98 tile_sets: Vec<TileSet>,
99 /// Individual tile definitions.
100 tiles: Vec<Tile>,
101}
102
103
104//---------------------------------------------------------------------------//
105// Implementation of TileDatabase
106//---------------------------------------------------------------------------//
107
108
109impl Decodeable for TileDatabase {
110
111 fn decode<R: ReadBytes>(data: &mut R, extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
112 let signature_bytes = data.read_slice(8, false)?;
113 if signature_bytes.as_slice() != SIGNATURE {
114 return Err(RLibError::DecodingFastBinUnsupportedSignature(signature_bytes));
115 }
116
117 let mut fastbin = Self::default();
118 fastbin.serialise_version = data.read_u16()?;
119
120 match fastbin.serialise_version {
121 1 => fastbin.read_v1(data, extra_data)?,
122 _ => return Err(RLibError::DecodingFastBinUnsupportedVersion(String::from("TileDatabase"), fastbin.serialise_version)),
123 }
124
125 // If we are not in the last byte, it means we didn't parse the entire file, which means this file is corrupt.
126 check_size_mismatch(data.stream_position()? as usize, data.len()? as usize)?;
127
128 Ok(fastbin)
129 }
130}
131
132impl Encodeable for TileDatabase {
133
134 fn encode<W: WriteBytes>(&mut self, buffer: &mut W, extra_data: &Option<EncodeableExtraData>) -> Result<()> {
135 buffer.write_all(SIGNATURE)?;
136 buffer.write_u16(self.serialise_version)?;
137
138 match self.serialise_version {
139 1 => self.write_v1(buffer, extra_data)?,
140 _ => return Err(RLibError::EncodingFastBinUnsupportedVersion(String::from("TileDatabase"), self.serialise_version)),
141 }
142
143 Ok(()) }
144}