use bevy::{core::FixedTimestep, prelude::*}; use bevy_reflect::TypeUuid; use bevy_rhai::*; use rhai::{plugin::*, AST}; #[derive(Debug, Clone, Copy, Default, Component)] pub struct Counter { count: i64, } #[rhai::export_module] mod counter_api { #[rhai_fn(get = "count", pure)] pub fn count(counter: &mut Counter) -> i64 { counter.count } #[rhai_fn(set = "count", pure)] pub fn set_count(counter: &mut Counter, count: i64) { counter.count = count } } fn main() { App::new() .add_plugins(DefaultPlugins) .add_asset::() .add_asset_loader( ScriptLoader::::new() .with_engine({ let mut engine = Engine::new_raw(); engine.disable_symbol("eval"); engine }) .add_extension("custom"), ) .add_startup_system(setup) .add_system_set( SystemSet::new() .with_run_criteria(FixedTimestep::steps_per_second(2.0)) .with_system(increment), ) .run() } #[derive(TypeUuid)] #[uuid = "fe38f050-725f-490e-8233-0692482b13aa"] struct CustomScript { ast: AST, } impl Script for CustomScript { fn from_ast(ast: AST) -> Self { Self { ast } } } fn setup(mut commands: Commands, asset_server: Res) { let increment: Handle = asset_server.load("increment.custom"); asset_server.watch_for_changes().unwrap(); commands .spawn() .insert(StandardEngine::with_engine({ let mut engine = Engine::new_raw(); engine.set_strict_variables(true); engine .disable_symbol("eval") .register_type_with_name::("Coutner") .register_global_module(exported_module!(counter_api).into()); engine })) .insert(StandardScope::default()) .insert(Counter::default()) .insert(increment); } fn increment( scripts: Res>, mut query: Query<( &StandardEngine, &Handle, &mut StandardScope, &mut Counter, )>, ) { for (engine, script, mut scope, mut counter) in query.iter_mut() { if let Some(script) = scripts.get(script) { scope.set_or_push("counter", *counter); engine.run_ast_with_scope(&mut scope, &script.ast).unwrap(); *counter = scope.get_value("counter").unwrap(); info!("Counter: {:?}", counter); } } }