Compare commits

..

1 commit

Author SHA1 Message Date
04bacb89d2 add macos and windows builds 2025-06-01 10:46:30 +02:00
32 changed files with 397 additions and 433 deletions

View file

@ -1,34 +0,0 @@
name: "Install Ruby"
inputs:
ruby-version:
required: true
runs:
using: "composite"
steps:
- name: Setup env
shell: bash
run: |
echo "PATH=/opt/rubies/${{ inputs.ruby-version }}/bin:$PATH" >> $GITHUB_ENV
echo "GEM_HOME=~/.gem/ruby/${{ inputs.ruby-version }}" >> $GITHUB_ENV
- name: Cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: |
/opt/rubies/${{ inputs.ruby-version }}
~/.gem/ruby/${{ inputs.ruby-version }}
key: ruby-static-${{ runner.os }}-${{ inputs.ruby-version }}
- name: Build static ruby
working-directory: /tmp
shell: bash
run: |
if [ -d /opt/rubies/${{inputs.ruby-version }} ]; then
echo "Ruby ${{ inputs.ruby-version }} already installed, skipping build"
else
git clone https://github.com/rbenv/ruby-build.git
PREFIX=/usr/local sudo -E ./ruby-build/install.sh
CC=clang RUBY_CONFIGURE_OPTS="--disable-shared" sudo -E ruby-build ${{ inputs.ruby-version }} /opt/rubies/${{ inputs.ruby-version }}
fi

View file

@ -10,10 +10,35 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: ./.github/actions/ruby_install
with: with:
ruby-version: "3.4.4" fetch-depth: 0
- name: Cache Ruby
id: cache-ruby
uses: actions/cache@v4
with:
path: rubies
key: ${{ runner.os }}-ruby
- name: Install Ruby
if: steps.cache-ruby.outputs.cache-hit != 'true'
env:
CC: clang
run: |
url="https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.4.tar.gz"
prefix=`pwd`/rubies/ruby-3.4
mkdir rubies
mkdir ruby_src
curl -sSL $url | tar -xz
cd ruby-3.4.4
mkdir build
cd build
../configure --without-shared --prefix=$prefix
make install
echo $prefix/bin >> $GITHUB_PATH
- name: Add Ruby to PATH
run: |
prefix=`pwd`/rubies/ruby-3.4
echo $prefix/bin >> $GITHUB_PATH
- name: Install latest mdbook - name: Install latest mdbook
run: | run: |
tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name')

View file

@ -11,19 +11,36 @@ env:
jobs: jobs:
build: build:
runs-on: [ubuntu-latest, macos-latest, windows-latest]
env: env:
RUSTFLAGS: -D warnings RUSTFLAGS: -D warnings
strategy:
matrix:
ruby-version: ["3.4.4"]
sys:
- os: ubuntu-latest
runs-on: ${{ matrix.sys.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: ./.github/actions/ruby_install - name: Cache Ruby
id: cache-ruby
uses: actions/cache@v4
with: with:
ruby-version: ${{ matrix.ruby-version }} path: rubies
key: ${{ runner.os }}-ruby
- name: Install Ruby
if: steps.cache-ruby.outputs.cache-hit != 'true'
env:
CC: clang
run: |
url="https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.4.tar.gz"
prefix=`pwd`/rubies/ruby-3.4
mkdir rubies
mkdir ruby_src
curl -sSL $url | tar -xz
cd ruby-3.4.4
mkdir build
cd build
../configure --without-shared --prefix=$prefix
make install
- name: Add Ruby to PATH
run: |
prefix=`pwd`/rubies/ruby-3.4
echo $prefix/bin >> $GITHUB_PATH
- name: Clippy - name: Clippy
run: cargo clippy --all-features --verbose -- -D warnings run: cargo clippy --all-features --verbose -- -D warnings
- name: Build - name: Build

View file

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_scriptum" name = "bevy_scriptum"
authors = ["Jaroslaw Konik <konikjar@gmail.com>"] authors = ["Jaroslaw Konik <konikjar@gmail.com>"]
version = "0.11.0" version = "0.9.0"
edition = "2024" edition = "2024"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
readme = "README.md" readme = "README.md"
@ -16,14 +16,14 @@ rhai = ["dep:rhai"]
ruby = ["dep:magnus", "dep:rb-sys"] ruby = ["dep:magnus", "dep:rb-sys"]
[dependencies] [dependencies]
bevy = { default-features = false, version = "0.18", features = ["bevy_asset", "bevy_log"] } bevy = { default-features = false, version = "0.16", features = ["bevy_asset", "bevy_log"] }
serde = "1.0.162" serde = "1.0.162"
rhai = { version = "1.14.0", features = [ rhai = { version = "1.14.0", features = [
"sync", "sync",
"internals", "internals",
"unchecked", "unchecked",
], optional = true } ], optional = true }
thiserror = "1.0.69" thiserror = "1.0.40"
anyhow = "1.0.82" anyhow = "1.0.82"
tracing = "0.1.40" tracing = "0.1.40"
mlua = { version = "0.9.8", features = [ mlua = { version = "0.9.8", features = [
@ -31,7 +31,7 @@ mlua = { version = "0.9.8", features = [
"vendored", "vendored",
"send", "send",
], optional = true } ], optional = true }
magnus = { version = "0.8.2", optional = true } magnus = { version = "0.7.1", optional = true }
rb-sys = { version = "0.9", default-features = false, features = ["link-ruby", "ruby-static"], optional = true } rb-sys = { version = "0.9", default-features = false, features = ["link-ruby", "ruby-static"], optional = true }
crossbeam-channel = "0.5.15" crossbeam-channel = "0.5.15"
libc = "0.2.172" libc = "0.2.172"

View file

@ -3,19 +3,21 @@
![demo](demo.gif) ![demo](demo.gif)
bevy_scriptum is a a plugin for [Bevy](https://bevyengine.org/) that allows you to write some of your game or application logic in a scripting language. bevy_scriptum is a a plugin for [Bevy](https://bevyengine.org/) that allows you to write some of your game or application logic in a scripting language.
### Supported scripting languages/runtimes ### Supported scripting languages/runtimes
| language/runtime | cargo feature | documentation chapter | | language/runtime | cargo feature | documentation chapter |
| ---------------------------------------------------- | ------------- | --------------------------------------------------------------- | | ---------------- | ------------- | --------------------------------------------------------------- |
| 🌙 LuaJIT | `lua` | [link](https://jarkonik.github.io/bevy_scriptum/lua/lua.html) | | 🌙 LuaJIT | `lua` | [link](https://jarkonik.github.io/bevy_scriptum/lua/lua.html) |
| 🌾 Rhai | `rhai` | [link](https://jarkonik.github.io/bevy_scriptum/rhai/rhai.html) | | 🌾 Rhai | `rhai` | [link](https://jarkonik.github.io/bevy_scriptum/rhai/rhai.html) |
| 💎 Ruby(currently only supported on Linux and MacOS) | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) | | 💎 Ruby | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) |
Documentation book is available [here](https://jarkonik.github.io/bevy_scriptum/) 📖 Documentation book is available [here](https://jarkonik.github.io/bevy_scriptum/) 📖
Full API docs are available at [docs.rs](https://docs.rs/bevy_scriptum/latest/bevy_scriptum/) 🧑‍💻 Full API docs are available at [docs.rs](https://docs.rs/bevy_scriptum/latest/bevy_scriptum/) 🧑‍💻
bevy_scriptum's main advantages include: bevy_scriptum's main advantages include:
- low-boilerplate - low-boilerplate
- easy to use - easy to use
- asynchronicity with a promise-based API - asynchronicity with a promise-based API
@ -25,6 +27,7 @@ bevy_scriptum's main advantages include:
Scripts are separate files that can be hot-reloaded at runtime. This allows you to quickly iterate on your game or application logic without having to recompile it. Scripts are separate files that can be hot-reloaded at runtime. This allows you to quickly iterate on your game or application logic without having to recompile it.
All you need to do is register callbacks on your Bevy app like this: All you need to do is register callbacks on your Bevy app like this:
```rust ```rust
use bevy::prelude::*; use bevy::prelude::*;
use bevy_scriptum::prelude::*; use bevy_scriptum::prelude::*;
@ -39,7 +42,9 @@ App::new()
}) })
.run(); .run();
``` ```
And you can call them in your scripts like this: And you can call them in your scripts like this:
```lua ```lua
hello_bevy() hello_bevy()
``` ```
@ -70,6 +75,7 @@ App::new()
``` ```
You can also pass arguments to your callback functions, just like you would in a regular Bevy system - using `In` structs with tuples: You can also pass arguments to your callback functions, just like you would in a regular Bevy system - using `In` structs with tuples:
```rust ```rust
use bevy::prelude::*; use bevy::prelude::*;
use bevy_scriptum::prelude::*; use bevy_scriptum::prelude::*;
@ -87,7 +93,9 @@ App::new()
}) })
.run(); .run();
``` ```
which you can then call in your script like this: which you can then call in your script like this:
```lua ```lua
fun_with_string_param("Hello world!") fun_with_string_param("Hello world!")
``` ```
@ -98,7 +106,7 @@ Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
bevy_scriptum = { version = "0.11", features = ["lua"] } bevy_scriptum = { version = "0.9", features = ["lua"] }
``` ```
or execute `cargo add bevy_scriptum --features lua` from your project directory. or execute `cargo add bevy_scriptum --features lua` from your project directory.
@ -161,14 +169,13 @@ You can also try running provided examples by cloning this repository and runnin
```bash ```bash
cargo run --example hello_world_lua cargo run --example hello_world_lua
``` ```
The examples live in `examples` directory and their corresponding scripts live in `assets/examples` directory within the repository. The examples live in `examples` directory and their corresponding scripts live in `assets/examples` directory within the repository.
### Bevy compatibility ### Bevy compatibility
| bevy version | bevy_scriptum version | | bevy version | bevy_scriptum version |
|--------------|-----------------------| | ------------ | --------------------- |
| 0.18 | 0.11 |
| 0.17 | 0.10 |
| 0.16 | 0.8-0.9 | | 0.16 | 0.8-0.9 |
| 0.15 | 0.7 | | 0.15 | 0.7 |
| 0.14 | 0.6 | | 0.14 | 0.6 |
@ -186,6 +193,7 @@ get_player_name():and_then(function(name)
print(name) print(name)
end) end)
``` ```
which will print out `John` when used with following exposed function: which will print out `John` when used with following exposed function:
```rust ```rust
@ -198,7 +206,7 @@ App::new()
.add_scripting::<LuaRuntime>(|runtime| { .add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("get_player_name"), || String::from("John")); runtime.add_function(String::from("get_player_name"), || String::from("John"));
}); });
```` ```
## Access entity from script ## Access entity from script
@ -206,6 +214,7 @@ A variable called `entity` is automatically available to all scripts - it repres
It exposes `index` property that returns bevy entity index. It exposes `index` property that returns bevy entity index.
It is useful for accessing entity's components from scripts. It is useful for accessing entity's components from scripts.
It can be used in the following way: It can be used in the following way:
```lua ```lua
print("Current entity index: " .. entity.index) print("Current entity index: " .. entity.index)
``` ```

View file

@ -7,7 +7,7 @@ currently being supported with security updates.
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 0.11 | :white_check_mark: | | 0.9 | :white_check_mark: |
## Reporting a Vulnerability ## Reporting a Vulnerability

510
book/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
[book] [book]
authors = ["Jaroslaw Konik"] authors = ["Jaroslaw Konik"]
language = "en" language = "en"
multilingual = false
src = "src" src = "src"
title = "bevy_scriptum" title = "bevy_scriptum"

View file

@ -2,8 +2,6 @@
| bevy version | bevy_scriptum version | | bevy version | bevy_scriptum version |
| ------------ | --------------------- | | ------------ | --------------------- |
| 0.18 | 0.11 |
| 0.17 | 0.10 |
| 0.16 | 0.8-0.9 | | 0.16 | 0.8-0.9 |
| 0.15 | 0.7 | | 0.15 | 0.7 |
| 0.14 | 0.6 | | 0.14 | 0.6 |

View file

@ -120,7 +120,7 @@ Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
bevy_scriptum = { version = "0.11", features = ["lua"] } bevy_scriptum = { version = "0.9", features = ["lua"] }
``` ```
or execute `cargo add bevy_scriptum --features lua` from your project directory. or execute `cargo add bevy_scriptum --features lua` from your project directory.

View file

@ -4,8 +4,8 @@ Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
bevy = "0.18" bevy = "0.16"
bevy_scriptum = { version = "0.11", features = ["lua"] } bevy_scriptum = { version = "0.9", features = ["lua"] }
``` ```
If you need a different version of bevy you need to use a matching bevy_scriptum If you need a different version of bevy you need to use a matching bevy_scriptum

View file

@ -4,8 +4,8 @@ Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
bevy = "0.18" bevy = "0.16"
bevy_scriptum = { version = "0.11", features = ["rhai"] } bevy_scriptum = { version = "0.9", features = ["rhai"] }
``` ```
If you need a different version of bevy you need to use a matching bevy_scriptum If you need a different version of bevy you need to use a matching bevy_scriptum

View file

@ -1,7 +1,5 @@
# Installation # Installation
Ruby is currently only supported on Linux ana MacOS.
## Ruby ## Ruby
To build `bevy_scriptum` with Ruby support a Ruby installation is needed to be To build `bevy_scriptum` with Ruby support a Ruby installation is needed to be
@ -13,20 +11,9 @@ After installing `rbenv` along with its `ruby-build` plugin you can build and
install a Ruby installation that will work with `bevy_scriptum` by executing: install a Ruby installation that will work with `bevy_scriptum` by executing:
```sh ```sh
CC=clang RUBY_CONFIGURE_OPTS="--disable-shared" rbenv install 3.4.4 CC=clang rbenv install 3.4.4
``` ```
Before building make sure you are using the correct Ruby version.
It can be done for example by executing `which ruby`.
Output should be similar to `/home/$USER/.rbenv/shims/ruby`.
If the version is not correct then refer to `rbenv` manual or documentation
relevant for your method of installation to switch to correct Ruby.
To set Ruby version for current shell for example `rbenv shell 3.4.4` can be
used.
If ruby-static installation can't be found its advisable to run `cargo clean`
before building as `rb-sys` may have cached an incorrect Ruby version.
Above assumes that you also have `clang` installed on your system. Above assumes that you also have `clang` installed on your system.
For `clang` installation instruction consult your For `clang` installation instruction consult your
OS vendor provided documentation or [clang official webiste](https://clang.llvm.org). OS vendor provided documentation or [clang official webiste](https://clang.llvm.org).
@ -45,8 +32,8 @@ Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
bevy = "0.18" bevy = "0.16"
bevy_scriptum = { version = "0.11", features = ["ruby"] } bevy_scriptum = { version = "0.9", features = ["ruby"] }
``` ```
If you need a different version of bevy you need to use a matching bevy_scriptum If you need a different version of bevy you need to use a matching bevy_scriptum

View file

@ -1,4 +1,3 @@
# Ruby # Ruby
This chapter demonstrates how to work with bevy_scriptum when using Ruby language runtime. This chapter demonstrates how to work with bevy_scriptum when using Ruby language runtime.
Ruby is currently only supported on Linux.

View file

@ -6,7 +6,7 @@ To enable live reload it should be enough to enable `file-watcher` feature
within bevy dependency in `Cargo.toml` within bevy dependency in `Cargo.toml`
```toml ```toml
bevy = { version = "0.18", features = ["file_watcher"] } bevy = { version = "0.16", features = ["file_watcher"] }
``` ```
## Init-teardown pattern ## Init-teardown pattern
@ -81,7 +81,7 @@ fn update(
fn teardown( fn teardown(
mut ev_asset: MessageReader<AssetEvent<LuaScript>>, mut ev_asset: EventReader<AssetEvent<LuaScript>>,
scripting_runtime: ResMut<LuaRuntime>, scripting_runtime: ResMut<LuaRuntime>,
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>, mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
) { ) {

View file

@ -8,7 +8,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_lua_on_update_from_rust) .add_systems(Update, call_lua_on_update_from_rust)
.add_scripting::<LuaRuntime>(|runtime| { .add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })

View file

@ -8,7 +8,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_lua_on_update_from_rust) .add_systems(Update, call_lua_on_update_from_rust)
.add_scripting::<LuaRuntime>(|runtime| { .add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })
@ -24,7 +24,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
fn call_lua_on_update_from_rust( fn call_lua_on_update_from_rust(
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>, mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
scripting_runtime: ResMut<LuaRuntime>, scripting_runtime: ResMut<LuaRuntime>,
mut exit: MessageWriter<AppExit>, mut exit: EventWriter<AppExit>,
) { ) {
for (entity, mut script_data) in &mut scripted_entities { for (entity, mut script_data) in &mut scripted_entities {
let val = scripting_runtime let val = scripting_runtime

View file

@ -33,7 +33,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
),)); ),));
} }
fn print_entity_names_and_quit(query: Query<&Name>, mut exit: MessageWriter<AppExit>) { fn print_entity_names_and_quit(query: Query<&Name>, mut exit: EventWriter<AppExit>) {
if !query.is_empty() { if !query.is_empty() {
for e in &query { for e in &query {
println!("{}", e); println!("{}", e);

View file

@ -8,7 +8,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_rhai_on_update_from_rust) .add_systems(Update, call_rhai_on_update_from_rust)
.add_scripting::<RhaiRuntime>(|runtime| { .add_scripting::<RhaiRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })

View file

@ -8,7 +8,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_rhai_on_update_from_rust) .add_systems(Update, call_rhai_on_update_from_rust)
.add_scripting::<RhaiRuntime>(|runtime| { .add_scripting::<RhaiRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })
@ -24,7 +24,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
fn call_rhai_on_update_from_rust( fn call_rhai_on_update_from_rust(
mut scripted_entities: Query<(Entity, &mut RhaiScriptData)>, mut scripted_entities: Query<(Entity, &mut RhaiScriptData)>,
scripting_runtime: ResMut<RhaiRuntime>, scripting_runtime: ResMut<RhaiRuntime>,
mut exit: MessageWriter<AppExit>, mut exit: EventWriter<AppExit>,
) { ) {
for (entity, mut script_data) in &mut scripted_entities { for (entity, mut script_data) in &mut scripted_entities {
let val = scripting_runtime let val = scripting_runtime

View file

@ -33,7 +33,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
),)); ),));
} }
fn print_entity_names_and_quit(query: Query<&Name>, mut exit: MessageWriter<AppExit>) { fn print_entity_names_and_quit(query: Query<&Name>, mut exit: EventWriter<AppExit>) {
if !query.is_empty() { if !query.is_empty() {
for e in &query { for e in &query {
println!("{}", e); println!("{}", e);

View file

@ -8,7 +8,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_ruby_on_update_from_rust) .add_systems(Update, call_ruby_on_update_from_rust)
.add_scripting::<RubyRuntime>(|runtime| { .add_scripting::<RubyRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })

View file

@ -10,7 +10,7 @@ fn main() {
.add_systems(Startup, startup) .add_systems(Startup, startup)
.add_systems(Update, call_lua_on_update_from_rust) .add_systems(Update, call_lua_on_update_from_rust)
.add_scripting::<RubyRuntime>(|runtime| { .add_scripting::<RubyRuntime>(|runtime| {
runtime.add_function(String::from("quit"), |mut exit: MessageWriter<AppExit>| { runtime.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
exit.write(AppExit::Success); exit.write(AppExit::Success);
}); });
}) })
@ -26,7 +26,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
fn call_lua_on_update_from_rust( fn call_lua_on_update_from_rust(
mut scripted_entities: Query<(Entity, &mut RubyScriptData)>, mut scripted_entities: Query<(Entity, &mut RubyScriptData)>,
scripting_runtime: ResMut<RubyRuntime>, scripting_runtime: ResMut<RubyRuntime>,
mut exit: MessageWriter<AppExit>, mut exit: EventWriter<AppExit>,
) { ) {
for (entity, mut script_data) in &mut scripted_entities { for (entity, mut script_data) in &mut scripted_entities {
let val = scripting_runtime let val = scripting_runtime

View file

@ -33,7 +33,7 @@ fn startup(mut commands: Commands, assets_server: Res<AssetServer>) {
),)); ),));
} }
fn print_entity_names_and_quit(query: Query<&Name>, mut exit: MessageWriter<AppExit>) { fn print_entity_names_and_quit(query: Query<&Name>, mut exit: EventWriter<AppExit>) {
if !query.is_empty() { if !query.is_empty() {
for e in &query { for e in &query {
println!("{}", e); println!("{}", e);

View file

@ -3,11 +3,9 @@ use std::marker::PhantomData;
use bevy::{ use bevy::{
asset::{io::Reader, Asset, AssetLoader, LoadContext}, asset::{io::Reader, Asset, AssetLoader, LoadContext},
tasks::ConditionalSendFuture, tasks::ConditionalSendFuture,
reflect::TypePath,
}; };
/// A loader for script assets. /// A loader for script assets.
#[derive(TypePath)]
pub struct ScriptLoader<A: Asset + From<String>> { pub struct ScriptLoader<A: Asset + From<String>> {
_phantom_data: PhantomData<A>, _phantom_data: PhantomData<A>,
} }

View file

@ -1,4 +1,4 @@
use bevy::{ecs::system::RunSystemError, prelude::*}; use bevy::prelude::*;
use core::any::TypeId; use core::any::TypeId;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -39,7 +39,7 @@ impl<R: Runtime> CallbackSystem<R> {
&mut self, &mut self,
call: &FunctionCallEvent<R::CallContext, R::Value>, call: &FunctionCallEvent<R::CallContext, R::Value>,
world: &mut World, world: &mut World,
) -> Result<R::Value, RunSystemError> { ) -> R::Value {
self.system.run(call.params.clone(), world) self.system.run(call.params.clone(), world)
} }
} }
@ -74,9 +74,7 @@ where
let mut inner_system = IntoSystem::into_system(self); let mut inner_system = IntoSystem::into_system(self);
inner_system.initialize(world); inner_system.initialize(world);
let system_fn = move |_args: In<Vec<R::Value>>, world: &mut World| { let system_fn = move |_args: In<Vec<R::Value>>, world: &mut World| {
let result = inner_system let result = inner_system.run((), world);
.run((), world)
.expect("Callback system failed to run");
inner_system.apply_deferred(world); inner_system.apply_deferred(world);
let mut runtime = world.get_resource_mut::<R>().expect("No runtime resource"); let mut runtime = world.get_resource_mut::<R>().expect("No runtime resource");
@ -114,7 +112,7 @@ macro_rules! impl_tuple {
) )
}); });
let result = inner_system.run(args, world).expect("Callback system failed to run"); let result = inner_system.run(args, world);
inner_system.apply_deferred(world); inner_system.apply_deferred(world);
let mut runtime = world.get_resource_mut::<RN>().expect("No runtime resource"); let mut runtime = world.get_resource_mut::<RN>().expect("No runtime resource");

View file

@ -5,10 +5,10 @@
//! ## Supported scripting languages/runtimes //! ## Supported scripting languages/runtimes
//! //!
//! | language/runtime | cargo feature | documentation chapter | //! | language/runtime | cargo feature | documentation chapter |
//! | ---------------------------------------------------- | ------------- | --------------------------------------------------------------- | //! | ----------------- | ------------- | --------------------------------------------------------------- |
//! | 🌙 LuaJIT | `lua` | [link](https://jarkonik.github.io/bevy_scriptum/lua/lua.html) | //! | 🌙 LuaJIT | `lua` | [link](https://jarkonik.github.io/bevy_scriptum/lua/lua.html) |
//! | 🌾 Rhai | `rhai` | [link](https://jarkonik.github.io/bevy_scriptum/rhai/rhai.html) | //! | 🌾 Rhai | `rhai` | [link](https://jarkonik.github.io/bevy_scriptum/rhai/rhai.html) |
//! | 💎 Ruby(currently only supported on Linux and MacOS) | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) | //! | 💎 Ruby | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) |
//! //!
//! Documentation book is available [here](https://jarkonik.github.io/bevy_scriptum/) 📖 //! Documentation book is available [here](https://jarkonik.github.io/bevy_scriptum/) 📖
//! //!
@ -103,7 +103,7 @@
//! //!
//! ```toml //! ```toml
//! [dependencies] //! [dependencies]
//! bevy_scriptum = { version = "0.11", features = ["lua"] } //! bevy_scriptum = { version = "0.9", features = ["lua"] }
//! ``` //! ```
//! //!
//! or execute `cargo add bevy_scriptum --features lua` from your project directory. //! or execute `cargo add bevy_scriptum --features lua` from your project directory.
@ -176,8 +176,6 @@
//! //!
//! | bevy version | bevy_scriptum version | //! | bevy version | bevy_scriptum version |
//! |--------------|-----------------------| //! |--------------|-----------------------|
//! | 0.18 | 0.11 |
//! | 0.17 | 0.10 |
//! | 0.16 | 0.8-0.9 | //! | 0.16 | 0.8-0.9 |
//! | 0.15 | 0.7 | //! | 0.15 | 0.7 |
//! | 0.14 | 0.6 | //! | 0.14 | 0.6 |
@ -282,12 +280,6 @@ pub enum ScriptingError {
NoSettingsResource, NoSettingsResource,
} }
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
pub enum ScriptSystemSet {
Reload,
Process,
}
/// Trait that represents a scripting runtime/engine. In practice it is /// Trait that represents a scripting runtime/engine. In practice it is
/// implemented for a scripint language interpreter and the implementor provides /// implemented for a scripint language interpreter and the implementor provides
/// function implementations for calling and registering functions within the interpreter. /// function implementations for calling and registering functions within the interpreter.
@ -441,14 +433,6 @@ impl<'a, R: Runtime> ScriptingRuntimeBuilder<'a, R> {
} }
} }
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
pub enum ScriptSystems {
Reload,
InitCallbacks,
ProcessNewScripts,
ProcessCalls,
}
impl BuildScriptingRuntime for App { impl BuildScriptingRuntime for App {
/// Adds a scripting runtime. Registers required bevy systems that take /// Adds a scripting runtime. Registers required bevy systems that take
/// care of processing and running the scripts. /// care of processing and running the scripts.
@ -464,7 +448,6 @@ impl BuildScriptingRuntime for App {
); );
} }
// Insert the runtime schedule after Update
self.world_mut() self.world_mut()
.resource_mut::<MainScheduleOrder>() .resource_mut::<MainScheduleOrder>()
.insert_after(Update, R::Schedule::default()); .insert_after(Update, R::Schedule::default());
@ -474,35 +457,22 @@ impl BuildScriptingRuntime for App {
.init_asset::<R::ScriptAsset>() .init_asset::<R::ScriptAsset>()
.init_resource::<Callbacks<R>>() .init_resource::<Callbacks<R>>()
.insert_resource(R::default()) .insert_resource(R::default())
.configure_sets(
R::Schedule::default(),
(
ScriptSystems::Reload,
ScriptSystems::InitCallbacks.after(ScriptSystems::Reload),
ScriptSystems::ProcessNewScripts.after(ScriptSystems::InitCallbacks),
ScriptSystems::ProcessCalls.after(ScriptSystems::ProcessNewScripts),
),
)
.add_systems( .add_systems(
R::Schedule::default(), R::Schedule::default(),
( (
reload_scripts::<R>.in_set(ScriptSystems::Reload), reload_scripts::<R>,
init_callbacks::<R>
.pipe(log_errors)
.in_set(ScriptSystems::InitCallbacks)
.after(ScriptSystems::Reload),
process_new_scripts::<R>
.pipe(log_errors)
.in_set(ScriptSystems::ProcessNewScripts)
.after(ScriptSystems::InitCallbacks),
process_calls::<R> process_calls::<R>
.pipe(log_errors) .pipe(log_errors)
.in_set(ScriptSystems::ProcessCalls) .after(process_new_scripts::<R>),
.after(ScriptSystems::ProcessNewScripts), init_callbacks::<R>.pipe(log_errors),
process_new_scripts::<R>
.pipe(log_errors)
.after(init_callbacks::<R>),
), ),
); );
let runtime = ScriptingRuntimeBuilder::<R>::new(self.world_mut()); let runtime = ScriptingRuntimeBuilder::<R>::new(self.world_mut());
f(runtime); f(runtime);
self self
@ -540,7 +510,7 @@ impl<R: Runtime> Default for Callbacks<R> {
} }
} }
#[cfg(all(debug_assertions, unix))] #[cfg(debug_assertions)]
pub extern "C" fn is_rdynamic_linking() -> bool { pub extern "C" fn is_rdynamic_linking() -> bool {
unsafe { unsafe {
// Get a function pointer to itself // Get a function pointer to itself
@ -554,12 +524,6 @@ pub extern "C" fn is_rdynamic_linking() -> bool {
} }
} }
#[cfg(any(not(debug_assertions), not(unix)))]
pub extern "C" fn is_rdynamic_linking() -> bool {
// On Windows or in release builds, return a default value
true
}
pub mod prelude { pub mod prelude {
pub use crate::{BuildScriptingRuntime as _, Runtime as _, Script}; pub use crate::{BuildScriptingRuntime as _, Runtime as _, Script};
} }

View file

@ -43,7 +43,7 @@ pub struct BevyEntity(pub Entity);
impl BevyEntity { impl BevyEntity {
pub fn index(&self) -> u32 { pub fn index(&self) -> u32 {
self.0.index_u32() self.0.index()
} }
} }
@ -104,7 +104,7 @@ impl Default for LuaRuntime {
let engine = engine.lock().expect("Failed to lock engine"); let engine = engine.lock().expect("Failed to lock engine");
engine engine
.register_userdata_type::<BevyEntity>(|typ| { .register_userdata_type::<BevyEntity>(|typ| {
typ.add_field_method_get("index", |_, entity| Ok(entity.index())); typ.add_field_method_get("index", |_, entity| Ok(entity.0.index()));
}) })
.expect("Failed to register BevyEntity userdata type"); .expect("Failed to register BevyEntity userdata type");

View file

@ -55,7 +55,7 @@ pub struct BevyEntity(pub Entity);
impl BevyEntity { impl BevyEntity {
pub fn index(&self) -> u32 { pub fn index(&self) -> u32 {
self.0.index_u32() self.0.index()
} }
} }

View file

@ -171,7 +171,7 @@ fn then(r_self: magnus::Value) -> magnus::Value {
} }
.as_value(), .as_value(),
)) ))
.into_value_with(&ruby) .into_value()
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -180,7 +180,7 @@ pub struct BevyEntity(pub Entity);
impl BevyEntity { impl BevyEntity {
pub fn index(&self) -> u32 { pub fn index(&self) -> u32 {
self.0.index_u32() self.0.index()
} }
} }
@ -448,11 +448,11 @@ impl Runtime for RubyRuntime {
let result = f( let result = f(
(), (),
args.iter() args.iter()
.map(|arg| RubyValue::new(arg.into_value_with(&ruby))) .map(|arg| RubyValue::new(arg.into_value()))
.collect(), .collect(),
) )
.expect("failed to call callback"); .expect("failed to call callback");
result.into_value_with(&ruby) result.into_value()
} }
self.execute_in_thread(Box::new(move |ruby: &Ruby| { self.execute_in_thread(Box::new(move |ruby: &Ruby| {
@ -527,8 +527,8 @@ impl<T: TryConvert> FromRuntimeValueWithEngine<'_, RubyRuntime> for T {
} }
impl<T: IntoValue> IntoRuntimeValueWithEngine<'_, T, RubyRuntime> for T { impl<T: IntoValue> IntoRuntimeValueWithEngine<'_, T, RubyRuntime> for T {
fn into_runtime_value_with_engine(value: T, engine: &magnus::Ruby) -> RubyValue { fn into_runtime_value_with_engine(value: T, _engine: &magnus::Ruby) -> RubyValue {
RubyValue::new(value.into_value_with(engine)) RubyValue::new(value.into_value())
} }
} }
@ -539,9 +539,9 @@ impl FuncArgs<'_, RubyValue, RubyRuntime> for () {
} }
impl<T: IntoValue> FuncArgs<'_, RubyValue, RubyRuntime> for Vec<T> { impl<T: IntoValue> FuncArgs<'_, RubyValue, RubyRuntime> for Vec<T> {
fn parse(self, engine: &magnus::Ruby) -> Vec<RubyValue> { fn parse(self, _engine: &magnus::Ruby) -> Vec<RubyValue> {
self.into_iter() self.into_iter()
.map(|x| RubyValue::new(x.into_value_with(engine))) .map(|x| RubyValue::new(x.into_value()))
.collect() .collect()
} }
} }
@ -562,9 +562,9 @@ macro_rules! impl_tuple {
impl<'a, $($t: IntoValue,)+> FuncArgs<'a, RubyValue, RubyRuntime> impl<'a, $($t: IntoValue,)+> FuncArgs<'a, RubyValue, RubyRuntime>
for ($($t,)+) for ($($t,)+)
{ {
fn parse(self, engine: &'a magnus::Ruby) -> Vec<RubyValue> { fn parse(self, _engine: &'a magnus::Ruby) -> Vec<RubyValue> {
vec![ vec![
$(RubyValue::new(self.$idx.into_value_with(engine)), )+ $(RubyValue::new(self.$idx.into_value()), )+
] ]
} }
} }

View file

@ -15,7 +15,7 @@ use super::components::Script;
/// Reloads scripts when they are modified. /// Reloads scripts when they are modified.
pub(crate) fn reload_scripts<R: Runtime>( pub(crate) fn reload_scripts<R: Runtime>(
mut commands: Commands, mut commands: Commands,
mut ev_asset: MessageReader<AssetEvent<R::ScriptAsset>>, mut ev_asset: EventReader<AssetEvent<R::ScriptAsset>>,
mut scripts: Query<(Entity, &mut Script<R::ScriptAsset>)>, mut scripts: Query<(Entity, &mut Script<R::ScriptAsset>)>,
) { ) {
for ev in ev_asset.read() { for ev in ev_asset.read() {
@ -149,9 +149,7 @@ pub(crate) fn process_calls<R: Runtime>(world: &mut World) -> Result<(), Scripti
.system .system
.lock() .lock()
.expect("Failed to lock callback system mutex"); .expect("Failed to lock callback system mutex");
let val = system let val = system.call(&call, world);
.call(&call, world)
.expect("Callback system call failed");
let mut runtime = world let mut runtime = world
.get_resource_mut::<R>() .get_resource_mut::<R>()
.ok_or(ScriptingError::NoRuntimeResource)?; .ok_or(ScriptingError::NoRuntimeResource)?;

View file

@ -441,7 +441,7 @@ macro_rules! scripting_tests {
assert_eq!( assert_eq!(
app.world().get_resource::<State>().unwrap().index, app.world().get_resource::<State>().unwrap().index,
entity.index_u32() entity.index()
); );
} }
@ -473,7 +473,7 @@ macro_rules! scripting_tests {
assert_eq!( assert_eq!(
app.world().get_resource::<State>().unwrap().index, app.world().get_resource::<State>().unwrap().index,
Some(entity.index_u32()) Some(entity.index())
); );
} }
@ -505,7 +505,7 @@ macro_rules! scripting_tests {
assert_eq!( assert_eq!(
app.world().get_resource::<State>().unwrap().index, app.world().get_resource::<State>().unwrap().index,
Some(entity.index_u32()) Some(entity.index())
); );
} }