~starkingdoms/starkingdoms

ref: e54fae7165cfad2269e971159960a03285d9d25a starkingdoms/crates/client/src/rendering/assets_wasm.rs -rw-r--r-- 3.5 KiB
e54fae71 — ghostly_zsh client networking probably working 10 months 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
use std::{collections::HashMap, fmt::Display, sync::{Arc, Mutex}};

use bevy_ecs::system::Resource;
use futures::channel::oneshot::{Receiver, Sender};
use image::EncodableLayout;
use tracing::info;
use wasm_bindgen_futures::spawn_local;

use super::texture::{self, Texture};

#[derive(Debug, Clone)]
pub enum AssetError {
    AssetNotFound,
    ResponseNotOk(u16),
}
impl Display for AssetError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AssetError::AssetNotFound => write!(f, "Asset not found"),
            AssetError::ResponseNotOk(code) => write!(f, "Server response was not ok {}", code),
        }
    }
}
impl std::error::Error for AssetError {}

#[derive(Resource)]
pub struct Assets {
    texture_receivers: Arc<Mutex<HashMap<String, Receiver<Vec<u8>>>>>,
    textures: Arc<Mutex<HashMap<String, Vec<u8>>>>,
}

impl Assets {
    pub fn new() -> Self {
        Assets {
            textures: Arc::new(Mutex::new(HashMap::new())),
            texture_receivers: Arc::new(Mutex::new(HashMap::new())),
        }
    }
    pub fn get(&self, local_path: impl Into<String>) -> Option<Vec<u8>> {
        let (tx, rx) = futures::channel::oneshot::channel();
        let local_path = local_path.into();
        let contains_texture = {
            self.textures.lock().unwrap().contains_key(&local_path)
        };
        let contains_texture_receiver = {
            self.texture_receivers.lock().unwrap().contains_key(&local_path)
        };
        if !contains_texture && !contains_texture_receiver {
            let textures = self.textures.clone();
            self.texture_receivers.lock().unwrap().insert(local_path.clone(), rx);
            spawn_local(async move {
                let window = web_sys::window().unwrap();
                let resp = match reqwest::get(format!("{}/src/textures/{}", window.location().origin().unwrap(), local_path)).await {
                    Ok(resp) => resp,
                    Err(e) => {
                        if e.is_request() {
                            panic!("Error in request {}", e);
                        } else if e.is_body() {
                            panic!("Error in body {}", e);
                        } else if e.is_status() {
                            panic!("Bad status: {}", e.status().unwrap());
                        } else if e.is_decode() {
                            panic!("Couldn't decode response's body {}", e);
                        } else if e.is_redirect() {
                            panic!("Response caused redirect loop {}", e);
                        } else if e.is_builder() {
                            panic!("Error in builder {}", e);
                        }
                        panic!();
                    },
                };
                let bytes = match resp.bytes().await {
                    Ok(bytes) => bytes,
                    Err(e) => todo!(),
                }.to_vec();
                textures.lock().unwrap().insert(local_path, bytes.clone());
                tx.send(bytes).unwrap();
            });
            None
        } else if !contains_texture {
            let mut texture_receivers = self.texture_receivers.lock().unwrap();
            let rx = texture_receivers.get_mut(&local_path).unwrap();
            if let Ok(Some(texture)) = rx.try_recv() {
                self.texture_receivers.lock().unwrap().remove(&local_path);
                return Some(texture);
            }
            None
        } else {
            self.textures.lock().unwrap().get(&local_path).cloned()
        }
    }
}