diff --git a/src/features/wonderevent/mod.rs b/src/features/wonderevent/mod.rs index bc40d1d..949e1d1 100644 --- a/src/features/wonderevent/mod.rs +++ b/src/features/wonderevent/mod.rs @@ -1,6 +1,8 @@ use self::components::{MaxFieldSize, WonderEventMessage}; use crate::features::phase::components::{CurrentPhase, Phase, TimerSettings}; use crate::prelude::*; +use std::sync::Mutex; +use std::sync::mpsc::{Receiver, Sender, channel}; use std::thread; use tungstenite::{Message as WsMessage, connect}; use url::Url; @@ -15,8 +17,24 @@ pub struct RequestWonderEvent { pub max_field_size: MaxFieldSize, } +#[derive(Resource)] +pub struct WonderEventSender(pub Sender); + +#[derive(Resource)] +pub struct WonderEventReceiver(pub Mutex>); + +#[derive(Component)] +struct FloatingText { + timer: Timer, + velocity: Vec3, +} + impl Plugin for WonderEventPlugin { fn build(&self, app: &mut App) { + let (tx, rx) = channel(); + app.insert_resource(WonderEventSender(tx)); + app.insert_resource(WonderEventReceiver(Mutex::new(rx))); + app.init_resource::(); app.add_message::(); app.add_systems( @@ -24,6 +42,8 @@ impl Plugin for WonderEventPlugin { ( check_halfway_focus.run_if(in_state(AppState::GameScreen)), handle_wonder_event_trigger, + handle_wonder_event_response.run_if(in_state(AppState::GameScreen)), + animate_floating_text, ), ); } @@ -75,10 +95,14 @@ fn check_halfway_focus( } } -fn handle_wonder_event_trigger(mut events: MessageReader) { +fn handle_wonder_event_trigger( + mut events: MessageReader, + sender: Res, +) { for event in events.read() { let url_str = event.url_str.clone(); let max_field_size = event.max_field_size.clone(); + let tx = sender.0.clone(); thread::spawn(move || { println!("WonderEvent: Connecting to {}", url_str); @@ -96,6 +120,25 @@ fn handle_wonder_event_trigger(mut events: MessageReader) { eprintln!("WonderEvent: Error sending message: {}", e); } else { println!("WonderEvent: Request sent successfully"); + + // Read response + if let Ok(msg) = socket.read() { + if let Ok(text) = msg.into_text() { + println!("WonderEvent: Received response: {}", text); + if let Ok(response) = + serde_json::from_str::(&text) + { + if let Err(e) = tx.send(response) { + eprintln!( + "WonderEvent: Failed to send response to main thread: {}", + e + ); + } + } else { + eprintln!("WonderEvent: Failed to parse response JSON"); + } + } + } } } else { eprintln!("WonderEvent: Error serializing request"); @@ -115,3 +158,98 @@ fn handle_wonder_event_trigger(mut events: MessageReader) { }); } } + +fn handle_wonder_event_response( + receiver: Res, + grid: Res, + mut tile_query: Query<&mut TileState>, + game_config: Res, + mut commands: Commands, +) { + if let Ok(rx) = receiver.0.try_lock() { + while let Ok(msg) = rx.try_recv() { + match msg { + WonderEventMessage::WonderGranted { position } => { + println!("WonderEvent: GRANTED at ({}, {})", position.x, position.y); + + // Update Tile State + if let Ok(_) = grid.map_tile_state( + (position.x, position.y), + |state| { + if let TileState::Occupied { + seed, + watered, + growth_stage, + withered, + dry_counter, + } = state + { + // Progress growth stage + let mut new_stage = *growth_stage; + if let Some(config) = seed.get_seed_config(&game_config) { + if new_stage < config.growth_stages { + new_stage += 1; + } + } + + TileState::Occupied { + seed: seed.clone(), + watered: *watered, + growth_stage: new_stage, + withered: *withered, + dry_counter: *dry_counter, + } + } else { + state.clone() + } + }, + tile_query.reborrow(), + ) { + let world_pos = grid_to_world_coords( + position.x, + position.y, + None, + grid.width, + grid.height, + ); + commands.spawn(( + Text2d::new("Wunder!"), + TextFont { + font_size: 20.0, + ..Default::default() + }, + TextColor(Color::srgb(1.0, 0.8, 0.2)), + Transform::from_translation(world_pos + Vec3::new(0.0, 20.0, 10.0)), + FloatingText { + timer: Timer::from_seconds(1.5, TimerMode::Once), + velocity: Vec3::new(0.0, 20.0, 0.0), + }, + )); + } + } + WonderEventMessage::RequestError { error } => { + println!("WonderEvent: REQUEST ERROR: {}", error); + } + WonderEventMessage::NoWonder => { + println!("WonderEvent: NO WONDER"); + } + _ => {} + } + } + } +} + +fn animate_floating_text( + mut commands: Commands, + time: Res