summaryrefslogtreecommitdiff
path: root/platforms/tortuise-script-compiled/src/lib.rs
blob: 47bc926bac9b5b1d39ba4430e352e508319687ab (plain)
use std::sync::Arc;

use tortuise::{file::FileManager, script::WasmRunner};

pub mod buffer;
pub mod entity;
pub mod input;
pub mod process;
pub mod random;
pub mod scene;
pub mod script;
pub mod state;
pub mod storage;
pub mod time;

pub struct ScriptContext<'a>(tortuise::script::FullScriptContext<'a>);

pub struct TortuiseScript {
	pub start: fn(cx: ScriptContext),
	pub update: fn(cx: ScriptContext),
	pub end: fn(cx: ScriptContext),
}

#[derive(Debug, Default, Clone)]
pub struct TortuiseScene {
	pub scripts: &'static [&'static str],
}

fn default_script(_cx: ScriptContext) {}

impl Default for TortuiseScript {
	fn default() -> Self {
		Self {
			start: default_script,
			update: default_script,
			end: default_script,
		}
	}
}

impl TortuiseScript {
	pub const fn empty() -> Self {
		Self {
			start: default_script,
			update: default_script,
			end: default_script,
		}
	}
}

#[doc(hidden)]
pub fn run_game(
	name: &str,
	author: &str,
	tld: &str,
	first_scene: &str,
	scenes: &[(&str, TortuiseScene)],
	scripts: &[(&str, TortuiseScript)],
) {
	use tortuise::manifest::HumaneGameManifest;

	fn wrap_script_fn(f: fn(ScriptContext)) -> tortuise::script::StaticScriptFunction {
		Some(Arc::new(move |c| f(ScriptContext(c))))
	}

	fn slice_to_boxed_slice(names: &[&str]) -> Box<[Box<str>]> {
		names.iter().cloned().map(Into::into).collect()
	}

	let manifest = HumaneGameManifest {
		name: Box::from(name),
		author: Box::from(author),
		tld: Box::from(tld),
		first_scene: Box::from(first_scene),
		scene: scenes
			.iter()
			.map(|(name, scene)| tortuise::manifest::PartialScene {
				name: (*name).into(),
				scripts: slice_to_boxed_slice(scene.scripts),
			})
			.collect(),
		script: scripts
			.iter()
			.map(
				|(name, script)| tortuise::script::ScriptDeclaration::Static {
					name: (*name).into(),
					start: wrap_script_fn(script.start),
					update: wrap_script_fn(script.update),
					end: wrap_script_fn(script.end),
				},
			)
			.collect(),
	};

	let mut files = FileManager::new();
	let wasm_runner = WasmRunner::new();
	let mut manifest = manifest.into();
	tortuise::init_logger(&manifest);
	if let Err(e) = tortuise::apply_patches(&mut manifest, &mut files, &wasm_runner) {
		log::error!("{e}");
	}
	tortuise::run_game(files, wasm_runner, manifest)
}

#[macro_export]
macro_rules! game {
	{
		name: $name: literal,
		author: $author: literal,
		tld: $tld: literal,
		first_scene: $first_scene: literal,
		scenes: { $($scene_name: literal => $scene: expr),* },
		scripts: { $($script_name: literal => $script: expr),* }
	} => {
		fn main() {
			$crate::run_game($name, $author, $tld, $first_scene, &[$(($scene_name, $scene),)*], &[$(($script_name, $script),)*]);
		}
	};
}