use bevy::prelude::*;
use crate::IssunSet;
use super::{
api_bindings,
backend::ScriptingBackend,
commands::{LuaCommand, LuaCommandQueue, LuaValue},
components::LuaScript,
mlua_backend::MluaBackend,
};
use crate::plugins::combat::components::Health;
pub struct ScriptingPlugin;
impl Plugin for ScriptingPlugin {
fn build(&self, app: &mut App) {
let backend = MluaBackend::new().expect("Failed to create MluaBackend");
api_bindings::register_all_apis(backend.lua()).expect("Failed to register Lua APIs");
app
.register_type::<LuaScript>()
.register_type::<LuaCommandQueue>()
.insert_non_send_resource(backend)
.init_resource::<LuaCommandQueue>()
.add_systems(
Update,
(load_scripts, execute_lua_commands)
.chain()
.in_set(IssunSet::Logic),
);
}
}
fn load_scripts(
mut backend: NonSendMut<MluaBackend>,
mut query: Query<(Entity, &mut LuaScript), Changed<LuaScript>>,
) {
for (entity, mut script) in query.iter_mut() {
if !script.is_loaded() {
info!("Loading script '{}' for entity {:?}", script.path, entity);
match backend.load_script(&script.path) {
Ok(handle) => {
script.set_loaded(handle);
info!("Successfully loaded script '{}'", script.path);
}
Err(e) => {
error!("Failed to load script '{}': {:?}", script.path, e);
}
}
}
}
}
fn execute_lua_commands(
mut commands: Commands,
mut queue: ResMut<LuaCommandQueue>,
entities: Query<Entity>,
) {
let queued_commands = queue.drain();
if !queued_commands.is_empty() {
info!("Executing {} Lua command(s)", queued_commands.len());
}
for command in queued_commands {
match command {
LuaCommand::SpawnEntity { scene_path } => {
warn!(
"SpawnEntity('{}') not yet implemented - requires DynamicScene loading",
scene_path
);
}
LuaCommand::DespawnEntity { entity } => {
if entities.get(entity).is_ok() {
commands.entity(entity).despawn();
info!("Despawned entity {:?}", entity);
} else {
warn!("Cannot despawn entity {:?} - already despawned", entity);
}
}
LuaCommand::InsertComponent {
entity,
type_name,
data,
} => {
if entities.get(entity).is_err() {
warn!(
"Cannot insert component '{}' on entity {:?} - entity despawned",
type_name, entity
);
continue;
}
match type_name.as_str() {
"Health" => {
let health = match &data {
LuaValue::Integer(max) => Health::new(*max as i32),
_ => {
warn!("Invalid data type for Health component: {:?}", data);
continue;
}
};
commands.entity(entity).insert(health);
info!("Inserted Health component on entity {:?}", entity);
}
_ => {
warn!(
"Unknown component type '{}' - only 'Health' is currently supported",
type_name
);
}
}
}
LuaCommand::RemoveComponent { entity, type_name } => {
if entities.get(entity).is_err() {
warn!(
"Cannot remove component '{}' from entity {:?} - entity despawned",
type_name, entity
);
continue;
}
warn!(
"RemoveComponent('{}') from entity {:?} not yet implemented - requires Reflection",
type_name, entity
);
}
}
}
}