use crate::error::{MulReaderError, MulReaderResult};
use crate::mul::MulReader;
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::{Cursor, Read, Seek, SeekFrom};
pub const BLOCK_SIZE: usize = 196;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Cell {
pub graphic: u16,
pub altitude: i8,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Block {
pub checksum: u32,
pub cells: [Cell; 64],
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct StaticLocation {
pub object_id: u16,
pub x: u8,
pub y: u8,
pub altitude: i8,
pub checksum: u16,
}
impl StaticLocation {
pub fn color_idx(&self) -> u16 {
self.object_id + 16384
}
}
pub fn read_block<T: Read + Seek>(data_reader: &mut T, id: u32) -> MulReaderResult<Block> {
data_reader.seek(SeekFrom::Start((id * BLOCK_SIZE as u32) as u64))?;
let mut block = Block {
checksum: data_reader.read_u32::<LittleEndian>()?,
cells: [Cell {
graphic: 0,
altitude: 0,
}; 64],
};
for i in 0..64 {
block.cells[i] = Cell {
graphic: data_reader.read_u16::<LittleEndian>()?,
altitude: data_reader.read_i8()?,
};
}
Ok(block)
}
pub fn read_block_statics<T: Read + Seek>(
mul_reader: &mut MulReader<T>,
id: u32,
) -> MulReaderResult<Vec<StaticLocation>> {
let raw = mul_reader.read(id)?;
let len = raw.data.len();
if len % 7 != 0 {
return Err(MulReaderError::UnexpectedSize {
expected: (len + (len % 7)) as u32,
found: len as u32,
});
}
let mut reader = Cursor::new(raw.data);
let mut statics = vec![];
for _i in 0..(len / 7) {
let object_id = reader.read_u16::<LittleEndian>()?;
let x = reader.read_u8()?;
let y = reader.read_u8()?;
let altitude = reader.read_i8()?;
let checksum = reader.read_u16::<LittleEndian>()?;
statics.push(StaticLocation {
object_id,
x,
y,
altitude,
checksum,
});
}
Ok(statics)
}