From 7aa6566796e1632ae36277648c162fc77af7052b Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 10 Jul 2026 19:42:23 -0400 Subject: State utilities --- src/lib.rs | 1 + src/main.rs | 9 +++++++ src/script.rs | 23 ++++++++++++++++ src/script/wasm.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 109 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 9c3162a..767eff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,5 @@ pub mod file; pub mod input; pub mod scene; pub mod script; +pub mod storage; pub mod time; diff --git a/src/main.rs b/src/main.rs index f5c869e..66e4cf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use tortuise::{ input::InputManager, scene::switch_scenes, script::{ScriptContext, ScriptManager, WasmRunner}, + storage::StorageManager, time::TimeContext, }; @@ -26,10 +27,17 @@ fn main() { 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(), @@ -58,6 +66,7 @@ fn main() { let mut context = ScriptContext { manifest: &manifest, buffer, + storage: &mut storage, input: &input, time: &time, operation_queue: Vec::new(), diff --git a/src/script.rs b/src/script.rs index 93f6f99..8539c92 100644 --- a/src/script.rs +++ b/src/script.rs @@ -7,6 +7,7 @@ use crate::{ file::{FileManager, GameManifest}, input::InputManager, scene::{preload_scene, switch_scenes}, + storage::StorageManager, time::TimeContext, }; @@ -15,6 +16,7 @@ mod wasm; pub struct ScriptManager<'a> { scripts: &'a [ScriptDeclaration], pub active_scripts: Vec, + entities: FxHashMap, Box<[u8]>>, script_states: FxHashMap>, } @@ -28,6 +30,7 @@ pub struct ScriptContext<'a> { pub buffer: &'a mut Buffer, pub input: &'a InputManager, pub time: &'a TimeContext, + pub storage: &'a mut StorageManager, pub operation_queue: Vec, } @@ -39,6 +42,7 @@ pub struct FullScriptContext<'a> { pub time: &'a TimeContext, pub scripts: &'a ScriptManager<'a>, pub files: &'a FileManager, + pub storage: &'a StorageManager, pub wasm_runner: &'a WasmRunner, pub operation_queue: &'a mut Vec, } @@ -55,6 +59,13 @@ pub enum Operation { script_id: usize, new_state: Box<[u8]>, }, + UpdateEntity { + name: Box, + new_state: Box<[u8]>, + }, + UpdateStorage { + new_save: Box<[u8]>, + }, Exit, } @@ -130,6 +141,7 @@ impl WasmRunner { buffer: context.buffer, input: context.input, time: context.time, + storage: context.storage, scripts, files, wasm_runner, @@ -160,6 +172,7 @@ impl<'a> ScriptManager<'a> { Self { scripts, active_scripts: Vec::new(), + entities: FxHashMap::default(), script_states: FxHashMap::default(), } } @@ -233,6 +246,7 @@ impl<'a> ScriptManager<'a> { buffer: context.buffer, input: context.input, time: context.time, + storage: context.storage, operation_queue: Vec::new(), }, files, @@ -248,6 +262,7 @@ impl<'a> ScriptManager<'a> { buffer: context.buffer, input: context.input, time: context.time, + storage: context.storage, operation_queue: Vec::new(), }, wasm_runner, @@ -260,6 +275,7 @@ impl<'a> ScriptManager<'a> { buffer: context.buffer, input: context.input, time: context.time, + storage: context.storage, operation_queue: Vec::new(), }, wasm_runner, @@ -269,6 +285,12 @@ impl<'a> ScriptManager<'a> { script_id, new_state, } => *get_script_state(&mut self.script_states, *script_id) = new_state.clone(), + Operation::UpdateEntity { name, new_state } => { + self.entities.insert(name.clone(), new_state.clone()); + } + Operation::UpdateStorage { new_save } => { + context.storage.background_save(new_save.clone()); + } Operation::Exit => context.exit(), } } @@ -328,6 +350,7 @@ impl<'a> ScriptManager<'a> { let Some(script) = self.scripts.get(script_id) else { unreachable!("The active script does not exist"); }; + self.script_states.remove(&script_id); match script { ScriptDeclaration::Static { end, .. } => { end.map(|s| { diff --git a/src/script/wasm.rs b/src/script/wasm.rs index a1b923b..5a9332e 100644 --- a/src/script/wasm.rs +++ b/src/script/wasm.rs @@ -328,7 +328,76 @@ fn save_state(mut caller: Caller>, offset: u32, length: u3 context.operation_queue.push(Operation::UpdateState { script_id: context.script_id, new_state, - }) + }); +} + +fn entity_size(caller: Caller>, name: u32, name_len: u32) -> u32 { + let context = caller.data(); + let name = unsafe { str_from_memory(&caller, name, name_len) }; + context + .scripts + .entities + .get(name) + .map(|entity| entity.len()) + .unwrap_or_default() as u32 +} + +fn load_entity(mut caller: Caller>, name: u32, name_len: u32, offset: u32) { + let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); + let name = unsafe { str_from_memory(&caller, name, name_len) }; + let context = caller.data(); + let entity = context + .scripts + .entities + .get(name) + .map(|entity| &**entity) + .unwrap_or(&[]); + memory.write(&mut caller, offset as usize, entity).unwrap(); +} + +fn save_entity( + mut caller: Caller>, + name: u32, + name_len: u32, + offset: u32, + length: u32, +) { + let offset = offset as usize; + let length = length as usize; + let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); + let new_state = Box::from(&memory.data(&caller)[offset..(offset + length)]); + let name = Box::from(unsafe { str_from_memory(&caller, name, name_len) }); + let context = caller.data_mut(); + context + .operation_queue + .push(Operation::UpdateEntity { name, new_state }); +} + +fn storage_size(caller: Caller>) -> u32 { + caller + .data() + .storage + .get() + .map(|data| data.len()) + .unwrap_or_default() as u32 +} + +fn load_storage(mut caller: Caller>, offset: u32) { + let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); + let context = caller.data(); + let state = context.storage.get().unwrap_or(&[]); + memory.write(&mut caller, offset as usize, state).unwrap(); +} + +fn save_storage(mut caller: Caller>, offset: u32, length: u32) { + let offset = offset as usize; + let length = length as usize; + let memory = caller.get_export("memory").unwrap().into_memory().unwrap(); + let new_save = Box::from(&memory.data(&caller)[offset..(offset + length)]); + let context = caller.data_mut(); + context + .operation_queue + .push(Operation::UpdateStorage { new_save }); } fn system_now(caller: Caller>) -> u64 { @@ -381,6 +450,12 @@ pub fn linker<'ctx>( state_size, load_state, save_state, + entity_size, + load_entity, + save_entity, + storage_size, + load_storage, + save_storage, system_now, monotonic_now, delta_time -- cgit v1.2.3