copy lua book chapters as starting point for ruby book
Some checks failed
Rust / build (pull_request) Has been cancelled

This commit is contained in:
Jaroslaw Konik 2025-05-26 16:59:56 +02:00
parent 679cfd8140
commit 35dc89322e
9 changed files with 484 additions and 0 deletions

View file

@ -0,0 +1,87 @@
# Builtin types
bevy_scriptum provides following types that can be used in Lua:
- ```Vec3```
- ```BevyEntity```
## Vec3
### Constructor
`Vec3(x: number, y: number, z: number)`
### Properties
- `x: number`
- `y: number`
- `z: number`
### Example Lua usage
```
my_vec = Vec3(1, 2, 3)
set_translation(entity, my_vec)
```
### Example Rust usage
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("set_translation"), set_translation);
})
.run();
}
fn set_translation(
In((entity, translation)): In<(BevyEntity, BevyVec3)>,
mut entities: Query<&mut Transform>,
) {
let mut transform = entities.get_mut(entity.0).unwrap();
transform.translation = translation.0;
}
```
## BevyEntity
### Constructor
None - instances can only be acquired by using built-in `entity` global variable.
### Properties
- `index: integer`
### Example Lua usage
```lua
print(entity.index)
pass_to_rust(entity)
```
### Example Rust usage
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("pass_to_rust"), |In((entity,)): In<(BevyEntity,)>| {
println!("pass_to_rust called with entity: {:?}", entity);
});
})
.run();
}
```

View file

@ -0,0 +1,13 @@
# Builtin variables
## entity
A variable called `entity` is automatically available to all scripts - it represents bevy entity that the `Script` component is attached to.
It exposes `index` property that returns bevy entity index.
It is useful for accessing entity's components from scripts.
It can be used in the following way:
```lua
print("Current entity index: " .. entity.index)
```
`entity` variable is currently not available within promise callbacks.

View file

@ -0,0 +1,121 @@
# Calling Rust from Lua
To call a rust function from Lua first you need to register a function
within Rust using builder pattern.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
// `runtime` is a builder that you can use to register functions
})
.run();
}
```
For example to register a function called `my_rust_func` you can do the following:
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("my_rust_func"), || {
println!("my_rust_func has been called");
});
})
.run();
}
```
After you do that the function will be available to Lua code in your spawned scripts.
```lua
my_rust_func()
```
Registered functions can also take parameters. A parameter can be any type
that implements `FromLua`.
Since a registered callback function is a Bevy system, the parameters are passed
to it as `In` struct with tuple, which has to be the first parameter of the closure.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("func_with_params"), |args: In<(String, i64)>| {
println!("my_rust_func has been called with string {} and i64 {}", args.0.0, args.0.1);
});
})
.run();
}
```
To make it look nicer you can destructure the `In` struct.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("func_with_params"), |In((a, b)): In<(String, i64)>| {
println!("my_rust_func has been called with string {} and i64 {}", a, b);
});
})
.run();
}
```
The above function can be called from Lua
```lua
func_with_params("abc", 123)
```
## Return value via promise
Any registered rust function that returns a value will retrurn a promise when
called within a script. By calling `:and_then` on the promise you can register
a callback that will receive the value returned from Rust function.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("returns_value"), || {
123
});
})
.run();
}
```
```lua
returns_value():and_then(function (value)
print(value) -- 123
end)
```

View file

@ -0,0 +1,67 @@
# Calling Lua from Rust
To call a function defined in Lua
```lua
function on_update()
end
```
We need to acquire `LuaRuntime` resource within a bevy system.
Then we will be able to call `call_fn` on it, providing the name
of the function to call, `LuaScriptData` that has been automatically
attached to entity after an entity with script attached has been spawned
and its script evaluated, the entity and optionally some arguments.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn call_lua_on_update_from_rust(
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
scripting_runtime: ResMut<LuaRuntime>,
) {
for (entity, mut script_data) in &mut scripted_entities {
// calling function named `on_update` defined in lua script
scripting_runtime
.call_fn("on_update", &mut script_data, entity, ())
.unwrap();
}
}
fn main() {}
```
We can also pass some arguments by providing a tuple or `Vec` as the last
`call_fn` argument.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn call_lua_on_update_from_rust(
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
scripting_runtime: ResMut<LuaRuntime>,
) {
for (entity, mut script_data) in &mut scripted_entities {
scripting_runtime
.call_fn("on_update", &mut script_data, entity, (123, String::from("hello")))
.unwrap();
}
}
fn main() {}
```
They will be passed to `on_update` Lua function
```lua
function on_update(a, b)
print(a) -- 123
print(b) -- hello
end
```
Any type that implements `IntoLua` can be passed as an argument withing the
tuple in `call_fn`.

View file

@ -0,0 +1,66 @@
# Hello World
After you are done installing the required crates, you can start developing
your first game or application using bevy_scriptum.
To start using the library you need to first import some structs and traits
with Rust `use` statements.
For convenience there is a main "prelude" module provided called
`bevy_scriptum::prelude` and a prelude for each runtime you have enabled as
a create feature.
You can now start exposing functions to the scripting language. For example, you can expose a function that prints a message to the console:
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(
String::from("my_print"),
|In((x,)): In<(String,)>| {
println!("my_print: '{}'", x);
},
);
})
.run();
}
```
Then you can create a script file in `assets` directory called `script.lua` that calls this function:
```lua
my_print("Hello world!")
```
And spawn an entity with attached `Script` component with a handle to a script source file:
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(
String::from("my_print"),
|In((x,)): In<(String,)>| {
println!("my_print: '{}'", x);
},
);
})
.add_systems(Startup,|mut commands: Commands, asset_server: Res<AssetServer>| {
commands.spawn(Script::<LuaScript>::new(asset_server.load("script.lua")));
})
.run();
}
```
You should then see `my_print: 'Hello world!'` printed in your console.

View file

@ -0,0 +1,12 @@
# Installation
Add the following to your `Cargo.toml`:
```toml
[dependencies]
bevy = "0.16"
bevy_scriptum = { version = "0.8", features = ["lua"] }
```
If you need a different version of bevy you need to use a matching bevy_scriptum
version according to the [bevy support matrix](../bevy_support_matrix.md)

View file

@ -0,0 +1,75 @@
# Interacting with bevy in callbacks
Every registered function is also just a regular Bevy system.
That allows you to do anything you would do in a Bevy system.
You could for example create a callback system function that prints names
of all entities with `Player` component.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
#[derive(Component)]
struct Player;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(
String::from("print_player_names"),
|players: Query<&Name, With<Player>>| {
for player in &players {
println!("player name: {}", player);
}
},
);
})
.run();
}
```
In script:
```lua
print_player_names()
```
You can use functions that interact with Bevy entities and resources and
take arguments at the same time. It could be used for example to mutate a
component.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
#[derive(Component)]
struct Player {
health: i32
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(
String::from("hurt_player"),
|In((hit_value,)): In<(i32,)>, mut players: Query<&mut Player>| {
let mut player = players.single_mut();
player.health -= hit_value;
},
);
})
.run();
}
```
And it could be called in script like:
```lua
hurt_player(5)
```

3
book/src/ruby/lua.md Normal file
View file

@ -0,0 +1,3 @@
# Lua
This chapter demonstrates how to work with bevy_scriptum when using Lua language runtime.

View file

@ -0,0 +1,40 @@
# Spawning scripts
To spawn a Lua script you will need to get a handle to a script asset using
bevy's `AssetServer`.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn my_spawner(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<LuaScript>::new(
assets_server.load("my_script.lua"),
));
}
fn main() {}
```
After they scripts have been evaled by bevy_scriptum, the entities that they've
been attached to will get the `Script::<LuaScript>` component stripped and instead
```LuaScriptData``` component will be attached.
So to query scipted entities you could do something like:
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
fn my_system(
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
) {
for (entity, mut script_data) in &mut scripted_entities {
// do something with scripted entities
}
}
fn main() {}
```