makspll / bevy_mod_scripting

Bevy Scripting Plugin
Apache License 2.0
401 stars 31 forks source link

add_default_component example? #66

Closed LaserWitch closed 1 year ago

LaserWitch commented 1 year ago

I've been trying to use add_default_component from lua, and despite get_type_by_name returning apparently correct data, and the type definitely being a component, the add errors out claiming there's no component. I'm not sure if this is on my end or the crates end? If it's on my end I could use an example of how to do it right.

makspll commented 1 year ago

I see, I think you're likely missing #[reflect(Reflect, Default)], here is an example which seems to work:

use bevy::app::AppExit;

use bevy::prelude::*;
use bevy_mod_scripting::prelude::*;

use bevy_script_api::lua::{bevy::LuaBevyAPIProvider, RegisterForeignLuaType};

#[derive(Component, Default, Reflect)]
#[reflect(Component, Default)]
pub struct DefComponent;

fn main() -> std::io::Result<()> {
    let mut app = App::new();

    app.add_plugins(DefaultPlugins)
        .add_plugins(ScriptingPlugin)
        .register_type::<DefComponent>()
        // note the implementation for Option is there, but we must register `LuaProxyable` for it
        .add_script_host::<LuaScriptHost<()>>(PostUpdate)
        .add_api_provider::<LuaScriptHost<()>>(Box::new(LuaBevyAPIProvider))
        .add_systems(Startup, |world: &mut World| {
            let entity = world.spawn(()).id();

            // run script
            world.resource_scope(|world, mut host: Mut<LuaScriptHost<()>>| {
                host.run_one_shot(
                    r#"
                        function once()
                            local my_component_type = world:get_type_by_name("DefComponent")
                            print("before: ", world:get_component(entity, my_component_type))
                            world:add_default_component(entity, my_component_type)
                            print("after: ", world:get_component(entity, my_component_type))
                        end
                        "#
                    .as_bytes(),
                    "script.lua",
                    entity,
                    world,
                    LuaEvent {
                        hook_name: "once".to_owned(),
                        args: (),
                        recipients: Recipients::All,
                    },
                )
                .expect("Something went wrong in the script!");
            });

            world.send_event(AppExit)
        });

    app.run();

    Ok(())
}

with the output being:

before:         nil
after:  bevy_api_lua::DefComponent
LaserWitch commented 1 year ago

You were right on the money, adding the reflect line to my struct got everything working right.