functional runtime

This commit is contained in:
2026-02-15 22:27:08 +08:00
parent 285fdcab1f
commit 44556ca3a1
5 changed files with 176 additions and 6 deletions

View File

@@ -1,10 +1,12 @@
use tauri::Manager;
use tracing::{error, info, warn};
use crate::get_app_handle;
use crate::{get_app_handle, lock_w};
use serde::{Deserialize, Serialize};
use serde_json;
use std::{fs, path::PathBuf};
use std::fs;
pub mod runtime;
#[derive(Serialize, Deserialize, Debug)]
pub struct ModuleMetadata {
@@ -13,7 +15,7 @@ pub struct ModuleMetadata {
pub description: Option<String>,
}
fn get_module_metadata(path: PathBuf) -> Option<ModuleMetadata> {
fn get_module_metadata(path: &std::path::Path) -> Option<ModuleMetadata> {
let metadata_path = path.join("metadata.json");
if metadata_path.exists() {
match fs::read_to_string(&metadata_path) {
@@ -65,6 +67,15 @@ pub fn init_modules() {
}
};
let state = lock_w!(crate::state::FDOLL);
let mut state_guard = match state.module_handles.lock() {
Ok(guard) => guard,
Err(e) => {
error!("Failed to lock module handles: {}", e);
return;
}
};
for entry in entries {
let entry = match entry {
Ok(entry) => entry,
@@ -76,12 +87,26 @@ pub fn init_modules() {
let path = entry.path();
if path.is_dir() {
let module_metadata = match get_module_metadata(path) {
let module_metadata = match get_module_metadata(&path) {
Some(metadata) => metadata,
None => continue,
};
dbg!(module_metadata);
// TODO: Initialize the module based on metadata
let script_path = path.join("main.lua");
if script_path.exists() {
match runtime::spawn_lua_runtime_from_path(&script_path) {
Ok(handle) => {
state_guard.push(handle);
}
Err(e) => {
error!(
"Failed to spawn runtime for module {}: {}",
module_metadata.name, e
);
}
}
} else {
warn!("Module {} has no main.lua script", module_metadata.name);
}
}
}
}

View File

@@ -0,0 +1,50 @@
use mlua::{Lua, UserData, UserDataMethods};
use std::{path::Path, thread, time::Duration};
use tracing::{error, info};
pub struct Engine;
impl UserData for Engine {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_method("log", |_, _, message: String| {
info!("{}", message);
Ok(())
});
methods.add_method("sleep", |_, _, seconds: u64| {
thread::sleep(Duration::from_secs(seconds));
Ok(())
});
}
}
fn load_script(path: &Path) -> Result<String, std::io::Error> {
std::fs::read_to_string(path)
}
fn setup_engine_globals(lua: &Lua) -> Result<(), mlua::Error> {
let globals = lua.globals();
globals.set("engine", Engine)
}
pub fn spawn_lua_runtime(script: &str) -> thread::JoinHandle<()> {
let script = script.to_string();
thread::spawn(move || {
let lua = Lua::new();
if let Err(e) = setup_engine_globals(&lua) {
error!("Failed to set engine global: {}", e);
return;
}
if let Err(e) = lua.load(&script).exec() {
error!("Failed to execute lua script: {}", e);
return;
}
})
}
pub fn spawn_lua_runtime_from_path(path: &Path) -> Result<thread::JoinHandle<()>, std::io::Error> {
let script = load_script(path)?;
Ok(spawn_lua_runtime(&script))
}

View File

@@ -19,6 +19,7 @@ pub struct AppState {
pub auth: AuthState,
pub user_data: AppData,
pub tray: Option<TrayIcon>,
pub module_handles: std::sync::Mutex<Vec<std::thread::JoinHandle<()>>>,
}
// Global application state
@@ -36,6 +37,7 @@ pub fn init_app_state() {
guard.network = init_network_state();
guard.auth = init_auth_state();
guard.user_data = AppData::default();
guard.module_handles = std::sync::Mutex::new(Vec::new());
}
update_display_dimensions_for_scene_state();
info!("Initialized FDOLL state (WebSocket client & user data initializing asynchronously)");