summaryrefslogtreecommitdiff
path: root/src/server/mining.rs
blob: f5d8dd8d59f57aa888566f7e828f14ade615b8c6 (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
extern crate serde_json;

use std::collections::HashMap;
use std::io::Write;

use crate::item::ItemType;
use crate::mass::{Mass, MassType};
use crate::math::Vector;
use crate::modules::mining::{Mining, MiningStatus};
use crate::modules::navigation::Navigation;
use crate::server::connection::ServerConnection;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MiningData {
    pub has_astroid_target: bool,
    pub astroid_has_minerals: bool,
    pub is_within_range: bool,
    pub status: MiningStatus,
    pub range: f64,
}

impl ServerConnection {
    pub fn server_mining(&mut self, masses: &mut HashMap<String, Mass>) {
        let mut ship = masses.remove(&self.name).unwrap();

        if let MassType::Ship {
            ref mut mining,
            ref mut storage,
            ref navigation,
            ..
        } = ship.mass_type
        {
            let mining_data = get_mining_data(ship.position.clone(), mining, navigation, masses);

            let send = serde_json::to_string(&mining_data).unwrap() + "\n";
            self.open = self.stream.write(send.as_bytes()).is_ok();

            let recv = self.receive();
            mining.give_recv(recv, mining_data);

            if mining.status == MiningStatus::Mined {
                if let Some(name) = navigation.target_name.clone() {
                    let target = masses.get_mut(&name).unwrap();
                    if let MassType::Astroid {
                        ref mut resources, ..
                    } = target.mass_type
                    {
                        match resources.take_item(ItemType::CrudeMinerals) {
                            Some(item) => {
                                if !storage.give_item(item.clone()) {
                                    let mass = Mass::new_item(
                                        item.clone(),
                                        ship.position.clone(),
                                        ship.velocity.clone(),
                                    );
                                    masses.insert(item.name.clone(), mass);
                                }
                            }
                            None => mining.off(),
                        }
                    }
                }
                mining.taken();
            }
        }

        masses.insert(self.name.clone(), ship);
    }
}

fn get_mining_data(
    position: Vector,
    mining: &Mining,
    navigation: &Navigation,
    masses: &mut HashMap<String, Mass>,
) -> MiningData {
    match navigation.target_name.clone() {
        Some(name) => {
            let target = masses.get(&name);

            let mut astroid_has_minerals = false;
            let has_astroid_target = match target {
                Some(target) => match target.mass_type {
                    MassType::Astroid { ref resources, .. } => {
                        astroid_has_minerals = resources
                            .items
                            .iter()
                            .any(|item| item.itemtype == ItemType::CrudeMinerals);
                        true
                    }
                    _ => false,
                },
                None => false,
            };

            let is_within_range = if has_astroid_target {
                match target {
                    Some(target) => mining.range > position.distance_from(target.position.clone()),
                    _ => false,
                }
            } else {
                false
            };

            MiningData {
                has_astroid_target,
                astroid_has_minerals,
                is_within_range,
                range: mining.range,
                status: mining.status.clone(),
            }
        }
        _ => MiningData {
            has_astroid_target: false,
            astroid_has_minerals: false,
            is_within_range: false,
            range: mining.range,
            status: mining.status.clone(),
        },
    }
}