1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use sc2_proto::sc2api;

use data::{ImageData, Point2, Rect2};
use {FromProto, IntoSc2, Result};

/// Info about the terrain.
#[derive(Debug, Clone)]
pub struct MapInfo {
    dimensions: (u32, u32),

    pathing_grid: ImageData,
    placement_grid: ImageData,
    terrain_height: ImageData,

    playable_area: Rect2,
    enemy_start_locations: Vec<Point2>,
}

impl MapInfo {
    /// Dimensions of the map.
    pub fn get_dimensions(&self) -> (u32, u32) {
        self.dimensions
    }

    /// Image that reveals pathable tiles.
    pub fn get_pathing_grid(&self) -> &ImageData {
        &self.pathing_grid
    }
    /// Image that reveals placable tiles.
    pub fn get_placement_grid(&self) -> &ImageData {
        &self.placement_grid
    }
    /// Image that reveals terrain height.
    pub fn get_terrain_height(&self) -> &ImageData {
        &self.terrain_height
    }

    /// Rectangle of the playable area.
    pub fn get_playable_area(&self) -> Rect2 {
        self.playable_area
    }
    /// Starting locations of the enemy bases.
    pub fn get_enemy_start_locations(&self) -> &[Point2] {
        &self.enemy_start_locations
    }
}

impl FromProto<sc2api::ResponseGameInfo> for MapInfo {
    fn from_proto(mut info: sc2api::ResponseGameInfo) -> Result<Self> {
        let mut start_raw = info.take_start_raw();

        Ok(Self {
            dimensions: (
                start_raw.get_map_size().get_x() as u32,
                start_raw.get_map_size().get_y() as u32,
            ),

            pathing_grid: start_raw.take_pathing_grid().into_sc2()?,
            placement_grid: start_raw.take_placement_grid().into_sc2()?,
            terrain_height: start_raw.take_terrain_height().into_sc2()?,

            playable_area: {
                let area = start_raw.get_playable_area();

                Rect2 {
                    from: Point2::new(
                        area.get_p0().get_x() as f32,
                        area.get_p0().get_y() as f32,
                    ),
                    to: Point2::new(
                        area.get_p1().get_x() as f32,
                        area.get_p1().get_y() as f32,
                    ),
                }
            },

            enemy_start_locations: start_raw
                .take_start_locations()
                .into_iter()
                .map(|p| Point2::new(p.get_x() as f32, p.get_y() as f32))
                .collect(),
        })
    }
}