From 0c128e472b1b49e32c313874eaeccc8c5f1b1202 Mon Sep 17 00:00:00 2001 From: Mica White Date: Mon, 26 Oct 2026 10:51:49 -0400 Subject: Finish engine --- src/lib.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 767eff9..1418ebd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,163 @@ pub mod buffer; pub mod file; pub mod input; +pub mod manifest; pub mod scene; pub mod script; pub mod storage; pub mod time; + +use crate::{ + buffer::{Buffer, Event}, + file::FileManager, + input::{Direction, InputManager, Position}, + manifest::GameManifest, + scene::switch_scenes, + script::{ScriptContext, ScriptManager, WasmRunner}, + storage::StorageManager, + time::TimeContext, +}; +use crossterm::event::MouseEventKind; +use etcetera::AppStrategy; +use prologger::{ColorMode, ProLogger, RotationConfig}; +use std::{ + fs::File, + io::{BufRead, BufWriter}, + path::PathBuf, + time::{Duration, Instant}, +}; + +pub fn apply_patches( + manifest: &mut GameManifest, + files: &mut FileManager, + wasm_compiler: &WasmRunner, +) -> std::io::Result<()> { + let path = etcetera::choose_app_strategy(manifest.app_strategy_args()) + .unwrap() + .in_config_dir("patches"); + let patchfile = File::open(path)?; + + let mut patches = Vec::new(); + for line in std::io::BufReader::new(patchfile).lines() { + let Ok(line) = line else { + continue; + }; + patches.push(line); + } + + for path in patches { + let path = PathBuf::from(path).into_boxed_path(); + let patch = files.load_file(path.clone(), wasm_compiler); + let patch = patch.as_ref().as_ref().unwrap(); + let patch = wasm_compiler.patch(patch)?; + manifest.apply_wasm_patch(path, patch); + } + + Ok(()) +} + +pub fn init_logger(manifest: &GameManifest) { + let path = etcetera::choose_app_strategy(manifest.app_strategy_args()) + .unwrap() + .in_state_dir("log") + .unwrap(); + let path = path.to_string_lossy(); + ProLogger::builder() + .with_rotating_file(&path, RotationConfig::new(100_000, 2)) + .with_color(ColorMode::Never) + .init() + .unwrap(); +} + +pub fn run_game(mut files: FileManager, wasm_runner: WasmRunner, manifest: GameManifest) { + let start = Instant::now(); + + let stdout = Box::new(BufWriter::new(std::io::stdout().lock())); + let mut framerate_limit: Option = None; + let mut buffer = Buffer::new(stdout).unwrap(); + let mut input = InputManager::new(); + let mut time = TimeContext::new(); + let mut storage = StorageManager::load(manifest.app_strategy_args()).unwrap(); + let mut scripts = ScriptManager::new(&manifest.scripts); + let mut context = ScriptContext { + framerate_limit: &mut framerate_limit, + manifest: &manifest, + buffer: &mut buffer, + storage: &mut storage, + input: &input, + time: &time, + operation_queue: Vec::new(), + }; + + let scene_start = Instant::now(); + switch_scenes( + &mut scripts, + &mut context, + &mut files, + &wasm_runner, + manifest.first_scene, + ); + log::info!( + "Switch scenes time: {} ms", + scene_start.elapsed().as_millis() + ); + + let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); + let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); + puffin::set_scopes_on(true); + + log::info!("Total startup time: {} ms", start.elapsed().as_millis()); + buffer + .render_loop(|buffer, event| match event { + Event::Key(event) => { + if event.is_press() { + input.press_key(event.code); + } + } + Event::Mouse(event) => { + match event.kind { + MouseEventKind::Down(_) => input.click_mouse(), + MouseEventKind::ScrollDown => input.scroll(Direction::Down), + MouseEventKind::ScrollUp => input.scroll(Direction::Up), + MouseEventKind::ScrollLeft => input.scroll(Direction::Left), + MouseEventKind::ScrollRight => input.scroll(Direction::Right), + _ => (), + } + + input.move_mouse(Position { + x: event.column, + y: event.row, + }); + } + Event::FocusChanged(is_focused) => { + if is_focused { + input.focus(); + } else { + input.unfocus(); + } + } + Event::Render => { + input.read_gil_events(); + buffer.cells.clear(); + let mut context = ScriptContext { + framerate_limit: &mut framerate_limit, + manifest: &manifest, + buffer, + storage: &mut storage, + input: &input, + time: &time, + operation_queue: Vec::new(), + }; + scripts.run_scripts(&mut context, &wasm_runner, &mut files); + files.reload_files(&wasm_runner); + input.reset_next_frame(); + if let Some(framerate_limit) = framerate_limit + && let Ok(elapsed) = time.system_now().elapsed() + { + std::thread::sleep(framerate_limit - elapsed); + } + time.next_frame(); + } + }) + .unwrap(); +} -- cgit v1.3.1