Skip to main content

rpgx_dioxus/
controller.rs

1use std::any::Any;
2
3use dioxus::prelude::*;
4use futures_util::stream::StreamExt;
5use log::error;
6use rpgx::library::Library;
7use rpgx::prelude::Engine;
8use rpgx::prelude::{Coordinates, Direction};
9
10#[derive(Clone, Debug)]
11pub enum Command {
12    WalkTo(Coordinates),
13    Step(Direction),
14}
15
16pub async fn sleep_ms(_ms: u64) {
17    #[cfg(feature = "web")]
18    {
19        gloo_timers::future::TimeoutFuture::new(_ms as u32).await;
20    }
21
22    #[cfg(feature = "desktop")]
23    {
24        tokio::time::sleep(std::time::Duration::from_millis(_ms)).await;
25    }
26}
27
28pub fn use_controller(
29    engine: Signal<Engine>,
30    library: Signal<Library<Box<dyn Any>>>,
31) -> Coroutine<Command> {
32    use_coroutine({
33        to_owned![engine];
34        move |mut rx: UnboundedReceiver<Command>| async move {
35            while let Some(command) = rx.next().await {
36                let result: Result<(), Box<dyn std::error::Error>> = async {
37                    match command {
38                        Command::WalkTo(target) => {
39                            let steps = engine.read().get_active_scene().unwrap().map.find_path(
40                                &engine
41                                    .read()
42                                    .get_active_scene()
43                                    .unwrap()
44                                    .pawn
45                                    .as_ref()
46                                    .unwrap()
47                                    .pointer,
48                                &target,
49                            );
50                            match steps {
51                                None => {
52                                    error!("Path not found");
53                                    return Err("Path not found".into());
54                                }
55                                Some(steps) => {
56                                    for step in steps {
57                                        sleep_ms(100).await;
58                                        engine
59                                            .write()
60                                            .get_active_scene_mut()
61                                            .unwrap()
62                                            .move_to(step)
63                                            .map_err(|e| {
64                                                Box::<dyn std::error::Error>::from(format!(
65                                                    "{:?}",
66                                                    e
67                                                ))
68                                            })?;
69                                    }
70                                    Ok(())
71                                }
72                            }
73                        }
74                        Command::Step(direction) => {
75                            let mut _engine = engine.write();
76                            if let Ok(pointer) =
77                                _engine.get_active_scene_mut().unwrap().step_to(direction)
78                            {
79                                _engine
80                                    .get_active_scene()
81                                    .unwrap()
82                                    .map
83                                    .get_actions_at(&pointer)
84                                    .into_iter()
85                                    .for_each(|action_id| {
86                                        if let Some(boxed) = library.read().get_by_id(action_id) {
87                                            if let Some(unboxed) =
88                                                boxed.downcast_ref::<Box<dyn Fn(&mut Engine)>>()
89                                            {
90                                                println!("calling unboxed action");
91                                                unboxed(&mut _engine)
92                                            }
93                                        }
94                                    });
95                                // for action_id in action_ids {
96                                //     // Keep this as log only or handle as needed
97                                //     log::info!("Action triggered: {:?}", action_id);
98                                // }
99                            }
100                            Ok(())
101                        }
102                    }
103                }
104                .await;
105
106                if let Err(e) = result {
107                    error!("Movement error: {:?}", e);
108                }
109            }
110        }
111    })
112}