summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2026-07-10 19:42:23 -0400
committerMica White <botahamec@outlook.com>2026-07-10 19:42:23 -0400
commit7aa6566796e1632ae36277648c162fc77af7052b (patch)
tree1f8362c44329acd519eb1c19cc65a3729e50313a /src
parenta9977e7fabeb06a6f21824cc4a41b36ea39f6799 (diff)
State utilities
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs9
-rw-r--r--src/script.rs23
-rw-r--r--src/script/wasm.rs77
4 files changed, 109 insertions, 1 deletions
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<usize>,
+ entities: FxHashMap<Box<str>, Box<[u8]>>,
script_states: FxHashMap<usize, Box<[u8]>>,
}
@@ -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<Operation>,
}
@@ -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<Operation>,
}
@@ -55,6 +59,13 @@ pub enum Operation {
script_id: usize,
new_state: Box<[u8]>,
},
+ UpdateEntity {
+ name: Box<str>,
+ 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<FullScriptContext<'_>>, offset: u32, length: u3
context.operation_queue.push(Operation::UpdateState {
script_id: context.script_id,
new_state,
- })
+ });
+}
+
+fn entity_size(caller: Caller<FullScriptContext<'_>>, 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<FullScriptContext<'_>>, 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<FullScriptContext<'_>>,
+ 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<FullScriptContext<'_>>) -> u32 {
+ caller
+ .data()
+ .storage
+ .get()
+ .map(|data| data.len())
+ .unwrap_or_default() as u32
+}
+
+fn load_storage(mut caller: Caller<FullScriptContext<'_>>, 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<FullScriptContext<'_>>, 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<FullScriptContext<'_>>) -> 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