summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 75068fda6c4d905da361626120e29edcceb2df82 (plain)
use std::io::BufWriter;

use bpaf::Bpaf;
use mimalloc::MiMalloc;
use prologger::{ColorMode, ProLogger, RotationConfig};
use tortuise::{
	buffer::{Buffer, Event},
	file::{FileManager, TomlGameManifest, normalize_game_manifest},
	input::InputManager,
	scene::switch_scenes,
	script::{ScriptContext, ScriptManager, WasmRunner},
	storage::StorageManager,
	time::TimeContext,
};

// #[global_allocator]
// static GLOBAL: MiMalloc = MiMalloc;

#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
enum Options {
	#[bpaf(command)]
	Run,
	#[bpaf(command)]
	Compile,
}

fn main() {
	let options = options().run();

	match options {
		Options::Compile => {
			let manifest = std::fs::read("tortuise.toml").unwrap();
			let manifest = toml::from_slice::<TomlGameManifest>(&manifest).unwrap();
			let manifest = normalize_game_manifest(manifest).unwrap();

			let manifest_decl = format!(
				r#"let manifest = GameManifest {{
					name: "{}".to_string(),
					first_scene: {},
					scenes: Box::from([{}]),
					scripts: Box::from([]),
				}}"#,
				manifest.name,
				manifest.first_scene,
				manifest
					.scenes
					.iter()
					.map(|scene| format!(
						r#"Scene {{
						name: \"{}\".to_string(),
						preload_scenes: Box::from([{}]),
						scripts: ResourceRequirements {{
							required: Box::from([{}]),
							preload: Box::from([{}]),
						}}
					}}"#,
						scene.name,
						scene
							.preload_scenes
							.iter()
							.map(|i| i.to_string())
							.collect::<Vec<_>>()
							.join(","),
						scene
							.scripts
							.required
							.iter()
							.map(|i| i.to_string())
							.collect::<Vec<_>>()
							.join(","),
						scene
							.scripts
							.preload
							.iter()
							.map(|i| i.to_string())
							.collect::<Vec<_>>()
							.join(","),
					))
					.collect::<Vec<_>>()
					.join(",")
			);
		}
		Options::Run => {
			ProLogger::builder()
				.with_rotating_file(".log", RotationConfig::new(100_000, 2))
				.with_color(ColorMode::Never)
				.init()
				.unwrap();

			let mut files = FileManager::default();
			let wasm_runner = WasmRunner::new();
			let manifest = files
				.load_file(Box::from("tortuise.toml".as_ref()), &wasm_runner)
				.unwrap()
				.unwrap_manifest()
				.clone();

			let stdout = Box::new(BufWriter::new(std::io::stdout().lock()));
			let mut buffer = Buffer::new(stdout).unwrap();
			let mut input = InputManager::new();
			let mut time = TimeContext::new();
			let mut storage = StorageManager::load(etcetera::AppStrategyArgs {
				top_level_domain: "com".into(),
				author: "botahamec".into(),
				app_name: manifest.name.to_string(),
			})
			.unwrap();
			let mut scripts = ScriptManager::new(&manifest.scripts);
			let mut context = ScriptContext {
				manifest: &manifest,
				buffer: &mut buffer,
				storage: &mut storage,
				input: &input,
				time: &time,
				operation_queue: Vec::new(),
			};

			switch_scenes(
				&mut scripts,
				&mut context,
				&mut files,
				&wasm_runner,
				manifest.first_scene,
			);

			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);
			buffer
				.render_loop(|buffer, event| match event {
					Event::Key(event) => {
						if event.is_press() {
							input.press_key(event.code);
						}
					}
					Event::Render => {
						buffer.cells.clear();
						let mut context = ScriptContext {
							manifest: &manifest,
							buffer,
							storage: &mut storage,
							input: &input,
							time: &time,
							operation_queue: Vec::new(),
						};
						scripts.run_scripts(&mut context, &wasm_runner, &mut files);
						input.reset_next_frame();
						time.next_frame();
					}
				})
				.unwrap();
		}
	}
}