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}