summaryrefslogtreecommitdiff
path: root/src/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/file.rs')
-rw-r--r--src/file.rs86
1 files changed, 70 insertions, 16 deletions
diff --git a/src/file.rs b/src/file.rs
index 2963879..20fdd68 100644
--- a/src/file.rs
+++ b/src/file.rs
@@ -4,7 +4,10 @@ use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use smol::{Task, block_on, unblock};
-use crate::scene::{Scene, scene_id_by_name};
+use crate::{
+ scene::{ResourceRequirements, Scene, scene_id_by_name},
+ script::ScriptDeclaration,
+};
type FileTask = Task<std::io::Result<FileData>>;
@@ -13,18 +16,39 @@ pub struct FileManager {
cache: FxHashMap<Box<Path>, FileData>,
}
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone)]
pub struct GameManifest {
pub name: Box<str>,
pub first_scene: usize,
pub scenes: Box<[Scene]>,
+ pub scripts: Box<[ScriptDeclaration]>,
}
#[derive(Debug, Serialize, Deserialize)]
struct TomlGameManifest {
name: Box<str>,
first_scene: Box<str>,
- scene: Box<[Scene]>,
+ #[serde(default)]
+ scene: Box<[TomlScene]>,
+ #[serde(default)]
+ script: Box<[TomlScript]>,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+struct TomlScene {
+ name: Box<str>,
+ #[serde(default)]
+ preload_scenes: Box<[Box<str>]>,
+ #[serde(default)]
+ scripts: Box<[Box<str>]>,
+ #[serde(default)]
+ preload_scripts: Box<[Box<str>]>,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(tag = "type", rename_all = "kebab-case")]
+enum TomlScript {
+ Wasm { name: Box<str>, path: Box<Path> },
}
pub enum FileData {
@@ -33,22 +57,50 @@ pub enum FileData {
}
fn normalize_game_manifest(manifest: TomlGameManifest) -> std::io::Result<GameManifest> {
- let first_scene = scene_id_by_name(&manifest.scene, &manifest.first_scene).ok_or(
+ let mut scripts = Vec::with_capacity(manifest.script.len());
+ let script_map: FxHashMap<Box<str>, usize> = manifest
+ .script
+ .into_iter()
+ .map(|script| match script {
+ TomlScript::Wasm { name, path } => {
+ scripts.push(ScriptDeclaration::Wasm { path });
+ (name, scripts.len() - 1)
+ }
+ })
+ .collect();
+ let scenes: Box<[Scene]> = manifest
+ .scene
+ .into_iter()
+ .map(|scene| Scene {
+ name: scene.name,
+ preload_scenes: Box::from([]),
+ scripts: ResourceRequirements {
+ required: scene
+ .scripts
+ .iter()
+ .map(|s| *script_map.get(s).unwrap())
+ .collect(),
+ preload: scene
+ .preload_scripts
+ .iter()
+ .map(|s| *script_map.get(s).unwrap())
+ .collect(),
+ },
+ })
+ .collect();
+ let first_scene = scene_id_by_name(&scenes, &manifest.first_scene).ok_or(
std::io::Error::other("Invalid first scene: scene not found"),
)?;
Ok(GameManifest {
name: manifest.name,
first_scene,
- scenes: manifest.scene,
+ scenes,
+ scripts: scripts.into_boxed_slice(),
})
}
fn compile_data(path: &Path, data: &[u8], compiler: &wasmi::Engine) -> std::io::Result<FileData> {
- if path == "manifest.postcard" {
- return Ok(FileData::GameManifest(
- postcard::from_bytes(data).map_err(std::io::Error::other)?,
- ));
- } else if path == "manifest.toml" {
+ if path == "manifest.toml" {
return Ok(FileData::GameManifest(normalize_game_manifest(
toml::from_slice(data).map_err(std::io::Error::other)?,
)?));
@@ -96,12 +148,14 @@ impl FileManager {
path: Box<Path>,
wasm_compiler: &wasmi::Engine,
) -> std::io::Result<&FileData> {
- let data = compile_data(
- path.as_ref(),
- &std::fs::read(path.as_ref()).map(Vec::into_boxed_slice)?,
- wasm_compiler,
- )?;
- self.cache.entry(path.clone()).insert_entry(data);
+ if !self.cache.contains_key(&path) {
+ let data = compile_data(
+ path.as_ref(),
+ &std::fs::read(path.as_ref()).map(Vec::into_boxed_slice)?,
+ wasm_compiler,
+ )?;
+ self.cache.entry(path.clone()).insert_entry(data);
+ }
Ok(self.cache.get(&path).unwrap())
}