~starkingdoms/starkingdoms

ref: f6a4a4cbf42b10fc967ec425dd01205622442e8f starkingdoms/crates/unified/src/server/craft.rs -rw-r--r-- 3.7 KiB
f6a4a4cbghostly_zsh feat: crafting removes resources from the ship now 19 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
use std::collections::HashMap;

use crate::{attachment::{PartInShip, Parts}, ecs::{CraftPartRequest, Part, Player, SingleStorage}, prelude::*, server::part::{SpawnPartBundle, SpawnPartRequest}};

pub fn craft_plugin(app: &mut App) {
    app.add_systems(Update, receive_crafting_request);
}

fn receive_crafting_request(
    mut craft_part_request: MessageReader<FromClient<CraftPartRequest>>,
    part_query: Query<(&Transform, &Part, &PartInShip)>,
    player_query: Query<(Entity, &Transform, &Part), With<Player>>,
    parts_query: Query<&Parts>,
    mut storage_query: Query<(&mut SingleStorage)>,
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    'request: for request in craft_part_request.read() {
        // TODO: make crafting take time
        let (transform, part, parts_list) = if let Ok((transform, part, part_in_ship)) = part_query.get(request.crafting_part) {
            // this is a normal part
            let Ok(parts_list) = parts_query.get(part_in_ship.0) else {
                warn!("Couldn't find parts list in part in ship");
                continue;
            };
            let parts_list = parts_list.iter().collect::<Vec<_>>();
            (transform, part, parts_list)
        } else if let Ok((entity, transform, part)) = player_query.get(request.crafting_part) {
            // this is a player
            let parts_list = if let Ok(parts_list) = parts_query.get(entity) {
                let mut parts_list = parts_list.iter().collect::<Vec<_>>();
                parts_list.push(entity);
                parts_list
            } else {
                vec![entity]
            };
            (transform, part, parts_list)
        } else {
            warn!("When receiving a crafting request, the crafting part didn't exist.");
            continue;
        };

        // find total resource in the ship
        let mut total_resource = HashMap::new();
        for part in parts_list.iter() {
            let Ok(storage) = storage_query.get_mut(*part) else {
                continue;
            };
            if let Some(resource) = total_resource.get_mut(&storage.resource_name) {
                *resource += storage.stored;
            } else {
                total_resource.insert(storage.resource_name.clone(), storage.stored);
            }
        }

        // check if resources in ship are sufficient
        for (resource_name, amount) in total_resource {
            if let Some(resource) = request.inputs.get(&resource_name) {
                if (*resource as f32) > amount {
                    continue 'request;
                }
            } else {
                // resource doesn't exist in the first place, continue
                continue 'request;
            }
        }
        // ok, we have enough resources

        // subtract recipe resources from ship
        let mut inputs = request.inputs.clone();
        for part in parts_list.iter() {
            let Ok(mut storage) = storage_query.get_mut(*part) else {
                continue;
            };
            if let Some(resource) = inputs.get_mut(&storage.resource_name) {
                if (*resource as f32) > storage.stored {
                    *resource -= storage.stored as u32;
                    storage.stored = 0.0;
                } else {
                    storage.stored -= *resource as f32;
                    inputs.remove(&storage.resource_name);
                }
            }
        }
        
        // ok, everything is good! spawn the part
        commands.spawn(SpawnPartBundle {
            req: SpawnPartRequest(asset_server.load(
                         format!("config/parts/{}.part.toml", request.crafted_part.to_lowercase()))),
            transform: transform.with_translation(transform.translation + vec3(50.0, 0.0, 0.0)),
        });
    }
}