Files
smart-rgb/crates/borders-wasm/src/bridge.rs
2025-10-10 20:00:55 -05:00

68 lines
2.8 KiB
Rust

//! WASM-JS bridge for game communication
//!
//! This module provides JavaScript bindings to expose game data and events
//! from the Bevy/WASM game to the React frontend.
use std::sync::{Arc, Mutex};
use wasm_bindgen::prelude::{JsValue, wasm_bindgen};
use borders_core::ui::protocol::{CameraStateUpdate, RenderInputEvent};
// Global state for input handling (needs to be accessible from Bevy systems)
lazy_static::lazy_static! {
static ref INPUT_STATE: Arc<Mutex<borders_core::ui::input::InputState>> =
Arc::new(Mutex::new(borders_core::ui::input::InputState::new()));
static ref CAMERA_STATE: Arc<Mutex<Option<CameraStateUpdate>>> =
Arc::new(Mutex::new(None));
}
/// Handle render input events from the frontend (clicks, keys, hover)
#[wasm_bindgen]
pub fn handle_render_input(event: JsValue) -> Result<(), JsValue> {
let event: RenderInputEvent = serde_wasm_bindgen::from_value(event).map_err(|e| JsValue::from_str(&format!("Failed to deserialize render input: {}", e)))?;
let mut state = INPUT_STATE.lock().map_err(|e| JsValue::from_str(&format!("Failed to lock input state: {}", e)))?;
// TODO: Get actual map width from GameView or TerrainData
let map_width = 2560; // Placeholder
borders_core::ui::handle_render_input(&event, &mut state, map_width).map_err(|e| JsValue::from_str(&e))
}
/// Handle camera state updates from the frontend
#[wasm_bindgen]
pub fn handle_camera_update(state: JsValue) -> Result<(), JsValue> {
let update: CameraStateUpdate = serde_wasm_bindgen::from_value(state).map_err(|e| JsValue::from_str(&format!("Failed to deserialize camera state: {}", e)))?;
let mut camera_state = CAMERA_STATE.lock().map_err(|e| JsValue::from_str(&format!("Failed to lock camera state: {}", e)))?;
borders_core::ui::handle_camera_update(update, &mut camera_state).map_err(|e| JsValue::from_str(&e))
}
/// Get the global input state (for Bevy systems to access)
pub fn get_input_state() -> Arc<Mutex<borders_core::ui::input::InputState>> {
INPUT_STATE.clone()
}
/// Track an analytics event
#[wasm_bindgen]
pub fn track_analytics_event(event: JsValue) -> Result<(), JsValue> {
#[derive(serde::Deserialize)]
struct AnalyticsEventPayload {
event: String,
#[serde(default)]
properties: std::collections::HashMap<String, serde_json::Value>,
}
let payload: AnalyticsEventPayload = serde_wasm_bindgen::from_value(event).map_err(|e| JsValue::from_str(&format!("Failed to deserialize analytics event: {}", e)))?;
let telemetry_event = borders_core::telemetry::TelemetryEvent { event: payload.event, properties: payload.properties };
// Spawn a task to track the event asynchronously
wasm_bindgen_futures::spawn_local(async move {
borders_core::telemetry::track(telemetry_event).await;
});
Ok(())
}