~starkingdoms/starkingdoms

ref: 8bbae28ef02dcef8ae19715d43d6b05edb8829ec starkingdoms/crates/unified/src/server/drill.rs -rw-r--r-- 5.9 KiB
8bbae28eghostly_zsh feat: variable storage on hearty appears to store things correctly 7 hours ago
                                                                                
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use crate::{attachment::{PartInShip, Parts}, config::planet::Planet, ecs::{Drill, Part, PlanetSensor, Player, SingleStorage, ToggleDrillEvent, VariableStorage}, prelude::*};

pub fn drill_plugin(app: &mut App) {
    app.add_systems(Update, (toggle_drill, drill_on_planet, do_drilling));
}

fn toggle_drill(
    mut toggle_drill_reader: MessageReader<FromClient<ToggleDrillEvent>>,
    mut drills: Query<&mut Drill>,
) {
    for toggle_drill_event in toggle_drill_reader.read() {
        // this getting of the drill also serves to check whether or not
        // the entity is a drill
        let Ok(mut drill) = drills.get_mut(toggle_drill_event.drill_entity) else { return };
        drill.drilling = !drill.drilling;
    }
}

fn drill_on_planet(
    mut collision_start: MessageReader<CollisionStart>,
    mut collision_end: MessageReader<CollisionEnd>,
    planet_sensors: Query<&PlanetSensor>,
    mut drills: Query<&mut Drill>,
) {
    for event in collision_start.read() {
        let (planet_sensor, mut drill) = if let (Ok(planet_sensor), Ok(drill)) = (planet_sensors.get(event.collider1), drills.get_mut(event.collider2)) {
            (planet_sensor, drill)
        } else if let (Ok(drill), Ok(planet_sensor)) = (drills.get_mut(event.collider1), planet_sensors.get(event.collider2)) {
            (planet_sensor, drill)
        } else {
            continue
        };
        drill.on_planet = Some(planet_sensor.0.clone());
    }
    for event in collision_end.read() {
        let (_, mut drill) = if let (Ok(planet_sensor), Ok(drill)) = (planet_sensors.get(event.collider1), drills.get_mut(event.collider2)) {
            (planet_sensor, drill)
        } else if let (Ok(drill), Ok(planet_sensor)) = (drills.get_mut(event.collider1), planet_sensors.get(event.collider2)) {
            (planet_sensor, drill)
        } else {
            continue
        };
        drill.drilling = false;
        drill.on_planet = None;
    }
}

fn do_drilling(
    drills: Query<(&Drill, &PartInShip)>,
    hearty_drills: Query<(Entity, &Drill), With<Player>>,
    parts_query: Query<&Parts>,
    mut single_storage_part_query: Query<&mut SingleStorage, With<Part>>,
    mut variable_storage_part_query: Query<&mut VariableStorage, With<Part>>,
    planet_query: Query<&Planet>,
    time: Res<Time>,
) {
    for (entity, drill) in hearty_drills {
        if !drill.drilling || drill.on_planet.is_none() {
            continue
        }
        let planet_name = drill.on_planet.clone().unwrap();
        let mut planet = None;
        for q_planet in planet_query {
            if q_planet.name == planet_name {
                planet = Some(q_planet);
                break;
            }
        }
        // if the planet name doesn't match a planet, we have a big problem
        let planet = planet.expect("In do_drilling, a planet name didn't match a planet");
        let Some(ref planet_resource) = planet.planet_resource else {
            continue
        };
        'adding_resources: {
            if let Ok(parts_list) = parts_query.get(entity) {
                for part_entity in parts_list.iter() {
                    let Ok(mut storage) = single_storage_part_query.get_mut(part_entity) else {
                        continue
                    };
                    let to_add = planet_resource.mining_speed * drill.resource_multiplier * time.delta_secs();
                    add_to_single_storage(&mut storage, to_add, &planet_resource.name);
                }
            }
            let Ok(mut storage) = variable_storage_part_query.get_mut(entity) else {
                break 'adding_resources;
            };
            let to_add = planet_resource.mining_speed * drill.resource_multiplier * time.delta_secs();
            add_to_variable_storage(&mut storage, to_add, &planet_resource.name);
        };
    }
    for (drill, part_in_ship) in drills {
        debug!("drill");
        if !drill.drilling || drill.on_planet.is_none() {
            continue
        }
        let planet_name = drill.on_planet.clone().unwrap();
        let mut planet = None;
        for q_planet in planet_query {
            if q_planet.name == planet_name {
                planet = Some(q_planet);
                break;
            }
        }
        // if the planet name doesn't match a planet, we have a big problem
        let planet = planet.expect("In do_drilling, a planet name didn't match a planet");
        let Some(ref planet_resource) = planet.planet_resource else {
            continue
        };
        let player = part_in_ship.0;
        let Ok(parts_list) = parts_query.get(player) else {
            error!("In do_drilling, there was a player without a Parts");
            continue
        };
        for part_entity in parts_list.iter() {
            let Ok(mut storage) = single_storage_part_query.get_mut(part_entity) else {
                continue
            };
            let to_add = planet_resource.mining_speed * drill.resource_multiplier * time.delta_secs();
            add_to_single_storage(&mut storage, to_add, &planet_resource.name);
        }
    }
}

fn add_to_variable_storage(
    storage: &mut VariableStorage,
    to_add: f32,
    resource_name: &String
) {
    let total_stored = storage.resources.iter().fold(0.0, |acc, (_, resource)| *resource + acc);
    if to_add + total_stored > storage.capacity {
        return;
    }
    if let Some(amount) = storage.resources.get_mut(resource_name) {
        *amount += to_add;
    } else {
        storage.resources.insert(resource_name.clone(), to_add);
    }
}

fn add_to_single_storage(
    storage: &mut SingleStorage,
    to_add: f32,
    resource_name: &String
) {
    if storage.resource_name.is_empty() {
        storage.resource_name = resource_name.clone();
    }
    // now that the name isn't empty, this will trigger
    if storage.resource_name == *resource_name {
        storage.stored += to_add;
        storage.stored = storage.stored.min(storage.capacity);
        return;
    }
}