// SPDX-FileCopyrightText: 2024 Joshua Goins // SPDX-License-Identifier: GPL-3.0-or-later use std::io::{Cursor, Seek}; use binrw::BinRead; use binrw::binrw; use crate::ByteSpan; #[binrw] #[derive(Debug, Clone, Copy)] #[brw(little)] struct PlatePosition { x: i16, y: i16 } #[binrw] #[derive(Debug)] #[brw(little)] struct TerrainHeader { version: u32, plate_count: u32, plate_size: u32, clip_distance: f32, unknown: f32, #[br(count = 32)] padding: Vec, #[br(count = plate_count)] positions: Vec } #[derive(Debug)] pub struct PlateModel { pub position: (f32, f32), pub filename: String } #[derive(Debug)] pub struct Terrain { pub plates: Vec } impl Terrain { /// Reads an existing TERA file pub fn from_existing(buffer: ByteSpan) -> Option { let mut cursor = Cursor::new(buffer); let header = TerrainHeader::read(&mut cursor).ok()?; let mut plates = vec![]; for i in 0..header.plate_count { plates.push(PlateModel { position: (header.plate_size as f32 * (header.positions[i as usize].x as f32 + 0.5), header.plate_size as f32 * (header.positions[i as usize].y as f32 + 0.5)), filename: format!("{:04}.mdl", i) }) } Some(Terrain { plates }) } }