Skip to main content

uorustlibs/map/
shared.rs

1use crate::error::{MulReaderError, MulReaderResult};
2use crate::mul::MulReader;
3use byteorder::{LittleEndian, ReadBytesExt};
4use std::io::{Cursor, Read, Seek, SeekFrom};
5
6pub const BLOCK_SIZE: usize = 196;
7
8/// An individual tile on a map
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub struct Cell {
11    /// A lookup into art.mul as to what the floor tile should be
12    pub graphic: u16,
13    /// How high the floor tile is.
14    /// When rendering, the reference point is the bottom right, the remaining corners are altered
15    /// to match the surrounding tiles
16    pub altitude: i8,
17}
18
19/// A block. Blocks contain a grid of 8x8 cells.
20///
21/// Blocks are stored in Maps in columns, top to bottom, left to right
22#[derive(Clone, Copy, PartialEq, Eq, Debug)]
23pub struct Block {
24    /// Unused
25    pub checksum: u32,
26    /// An 8x8 grid of cells, stored in rows.
27    /// The first row is the top of the block, working downwards
28    pub cells: [Cell; 64],
29}
30
31/// The location of a fixed map prop, relative to a block
32#[derive(Clone, Copy, PartialEq, Eq, Debug)]
33pub struct StaticLocation {
34    /// A lookup into art.mul, as to what the static should be
35    pub object_id: u16,
36    /// The x location of the prop
37    pub x: u8,
38    /// The y location of the prop (increasing y means further downwards)
39    pub y: u8,
40    /// How high to render this item
41    pub altitude: i8,
42    /// Unused
43    pub checksum: u16,
44}
45
46impl StaticLocation {
47    /// Find the position in RadarCol that contains the color to render in the minimap
48    pub fn color_idx(&self) -> u16 {
49        self.object_id + 16384
50    }
51}
52
53/// Read a block from a map, or a diff file
54pub fn read_block<T: Read + Seek>(data_reader: &mut T, id: u32) -> MulReaderResult<Block> {
55    //Cycle to id * 192
56    data_reader.seek(SeekFrom::Start((id * BLOCK_SIZE as u32) as u64))?;
57    //Read the header
58    let mut block = Block {
59        checksum: data_reader.read_u32::<LittleEndian>()?,
60        cells: [Cell {
61            graphic: 0,
62            altitude: 0,
63        }; 64],
64    };
65    //Read 64 cells
66    for i in 0..64 {
67        block.cells[i] = Cell {
68            graphic: data_reader.read_u16::<LittleEndian>()?,
69            altitude: data_reader.read_i8()?,
70        };
71    }
72    Ok(block)
73}
74
75/// Read static locations from a map, or from a diff file
76pub fn read_block_statics<T: Read + Seek>(
77    mul_reader: &mut MulReader<T>,
78    id: u32,
79) -> MulReaderResult<Vec<StaticLocation>> {
80    let raw = mul_reader.read(id)?;
81    let len = raw.data.len();
82    if len % 7 != 0 {
83        return Err(MulReaderError::UnexpectedSize {
84            expected: (len + (len % 7)) as u32,
85            found: len as u32,
86        });
87    }
88    let mut reader = Cursor::new(raw.data);
89    let mut statics = vec![];
90    for _i in 0..(len / 7) {
91        let object_id = reader.read_u16::<LittleEndian>()?;
92        let x = reader.read_u8()?;
93        let y = reader.read_u8()?;
94        let altitude = reader.read_i8()?;
95        let checksum = reader.read_u16::<LittleEndian>()?;
96        statics.push(StaticLocation {
97            object_id,
98            x,
99            y,
100            altitude,
101            checksum,
102        });
103    }
104    Ok(statics)
105}