mod world; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use tiny_http::{Header, Response, Server}; use world::World; const INDEX: &str = include_str!("index.html"); fn main() { let seed = std::env::args() .nth(1) .and_then(|s| s.parse().ok()) .unwrap_or(42u64); let addr = std::env::var("SIM_ADDR").unwrap_or_else(|_| "127.0.0.1:7878".into()); let world = Arc::new(Mutex::new(World::new(seed))); { let world = Arc::clone(&world); thread::spawn(move || { loop { world.lock().unwrap().step(); thread::sleep(Duration::from_millis(100)); } }); } let server = Server::http(&addr).expect("failed to bind"); println!("Simulation running at http://{addr}"); for req in server.incoming_requests() { let world = Arc::clone(&world); thread::spawn(move || { let (body, ctype) = match req.url() { "/" => (INDEX.to_string(), "text/html; charset=utf-8"), "/api/terrain" => (world.lock().unwrap().terrain_json(), "application/json"), "/api/state" => (world.lock().unwrap().state_json(), "application/json"), _ => { let _ = req.respond(Response::from_string("not found").with_status_code(404)); return; } }; let header = Header::from_bytes("Content-Type", ctype).unwrap(); let _ = req.respond(Response::from_string(body).with_header(header)); }); } }