Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa70abac23 | ||
| 41d0fd57f3 | |||
|
|
e430795dce |
10 changed files with 43 additions and 163 deletions
|
|
@ -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.9.0"
|
version = "0.9.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
@ -35,7 +35,6 @@ 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"
|
||||||
tempfile = "3.20.0"
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "call_function_from_rust_rhai"
|
name = "call_function_from_rust_rhai"
|
||||||
|
|
|
||||||
19
README.md
19
README.md
|
|
@ -3,21 +3,19 @@
|
||||||

|

|
||||||
|
|
||||||
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 | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) |
|
| 💎 Ruby(currently only supported on Linux) | `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
|
||||||
|
|
@ -27,7 +25,6 @@ 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::*;
|
||||||
|
|
@ -42,9 +39,7 @@ 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()
|
||||||
```
|
```
|
||||||
|
|
@ -75,7 +70,6 @@ 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::*;
|
||||||
|
|
@ -93,9 +87,7 @@ 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!")
|
||||||
```
|
```
|
||||||
|
|
@ -169,13 +161,12 @@ 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.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 |
|
||||||
|
|
@ -193,7 +184,6 @@ 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
|
||||||
|
|
@ -206,7 +196,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
|
||||||
|
|
||||||
|
|
@ -214,7 +204,6 @@ 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)
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
def async_fun
|
get_player_name.and_then do |name|
|
||||||
async do
|
puts name
|
||||||
a = get_player_name
|
|
||||||
b = a
|
|
||||||
puts '0'
|
|
||||||
puts a.await
|
|
||||||
puts '1'
|
|
||||||
u = get_player_name
|
|
||||||
puts b.await
|
|
||||||
puts '2'
|
|
||||||
z = get_player_name
|
|
||||||
puts z
|
|
||||||
puts z.await
|
|
||||||
puts "end"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
async_fun.await
|
|
||||||
puts "after await"
|
|
||||||
|
|
||||||
quit
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
|
Ruby is currently only supported on Linux.
|
||||||
|
|
||||||
## 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
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
# 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.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_scripting::<RubyRuntime>(|builder| {
|
.add_scripting::<RubyRuntime>(|builder| {
|
||||||
builder
|
builder.add_function(
|
||||||
.add_function(
|
|
||||||
String::from("get_player_name"),
|
String::from("get_player_name"),
|
||||||
|player_names: Query<&Name, With<Player>>| {
|
|player_names: Query<&Name, With<Player>>| {
|
||||||
player_names
|
player_names
|
||||||
|
|
@ -18,10 +17,7 @@ fn main() {
|
||||||
.expect("Missing player_names")
|
.expect("Missing player_names")
|
||||||
.to_string()
|
.to_string()
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
.add_function(String::from("quit"), |mut exit: EventWriter<AppExit>| {
|
|
||||||
exit.write(AppExit::Success);
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.add_systems(Startup, startup)
|
.add_systems(Startup, startup)
|
||||||
.run();
|
.run();
|
||||||
|
|
|
||||||
14
src/lib.rs
14
src/lib.rs
|
|
@ -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 | `ruby` | [link](https://jarkonik.github.io/bevy_scriptum/ruby/ruby.html) |
|
//! | 💎 Ruby(currently only supported on Linux) | `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/) 📖
|
||||||
//!
|
//!
|
||||||
|
|
@ -375,8 +375,6 @@ pub trait Runtime: Resource + Default {
|
||||||
fn needs_rdynamic_linking() -> bool {
|
fn needs_rdynamic_linking() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume(&self, fiber: &Self::Value, value: &Self::Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FuncArgs<'a, V, R: Runtime> {
|
pub trait FuncArgs<'a, V, R: Runtime> {
|
||||||
|
|
@ -512,7 +510,7 @@ impl<R: Runtime> Default for Callbacks<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(all(debug_assertions, unix))]
|
||||||
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
|
||||||
|
|
@ -526,6 +524,12 @@ 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};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ pub(crate) struct PromiseInner<C: Send, V: Send> {
|
||||||
pub(crate) callbacks: Vec<PromiseCallback<C, V>>,
|
pub(crate) callbacks: Vec<PromiseCallback<C, V>>,
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub(crate) context: C,
|
pub(crate) context: C,
|
||||||
pub(crate) resolved_value: Option<V>,
|
|
||||||
pub(crate) fibers: Vec<V>, // TODO: should htis be vec or option
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that represents a Promise.
|
/// A struct that represents a Promise.
|
||||||
|
|
@ -53,31 +51,12 @@ impl<C: Clone + Send + 'static, V: Send + Clone> Promise<C, V> {
|
||||||
where
|
where
|
||||||
R: Runtime<Value = V, CallContext = C>,
|
R: Runtime<Value = V, CallContext = C>,
|
||||||
{
|
{
|
||||||
let mut fibers: Vec<V> = vec![];
|
|
||||||
if let Ok(mut inner) = self.inner.lock() {
|
if let Ok(mut inner) = self.inner.lock() {
|
||||||
inner.resolved_value = Some(val.clone());
|
inner.resolve(runtime, val)?;
|
||||||
inner.resolve(runtime, val.clone())?;
|
|
||||||
|
|
||||||
for fiber in inner.fibers.drain(..) {
|
|
||||||
fibers.push(fiber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for fiber in fibers {
|
|
||||||
runtime.resume(&fiber, &val.clone());
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a fiber that will be resumed when the [Promise] is resolved.
|
|
||||||
#[cfg(any(feature = "rhai", feature = "lua", feature = "ruby"))]
|
|
||||||
pub(crate) fn await_promise(&mut self, fiber: V) {
|
|
||||||
let mut inner = self
|
|
||||||
.inner
|
|
||||||
.lock()
|
|
||||||
.expect("Failed to lock inner promise mutex");
|
|
||||||
inner.fibers.push(fiber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register a callback that will be called when the [Promise] is resolved.
|
/// Register a callback that will be called when the [Promise] is resolved.
|
||||||
#[cfg(any(feature = "rhai", feature = "lua", feature = "ruby"))]
|
#[cfg(any(feature = "rhai", feature = "lua", feature = "ruby"))]
|
||||||
pub(crate) fn then(&mut self, callback: V) -> Self {
|
pub(crate) fn then(&mut self, callback: V) -> Self {
|
||||||
|
|
@ -86,10 +65,8 @@ impl<C: Clone + Send + 'static, V: Send + Clone> Promise<C, V> {
|
||||||
.lock()
|
.lock()
|
||||||
.expect("Failed to lock inner promise mutex");
|
.expect("Failed to lock inner promise mutex");
|
||||||
let following_inner = Arc::new(Mutex::new(PromiseInner {
|
let following_inner = Arc::new(Mutex::new(PromiseInner {
|
||||||
fibers: vec![],
|
|
||||||
callbacks: vec![],
|
callbacks: vec![],
|
||||||
context: inner.context.clone(),
|
context: inner.context.clone(),
|
||||||
resolved_value: None,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
inner.callbacks.push(PromiseCallback {
|
inner.callbacks.push(PromiseCallback {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
io::Write,
|
|
||||||
sync::{Arc, Condvar, LazyLock, Mutex},
|
sync::{Arc, Condvar, LazyLock, Mutex},
|
||||||
thread::{self, JoinHandle},
|
thread::{self, JoinHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ::magnus::{
|
use ::magnus::{typed_data::Inspect, value::Opaque};
|
||||||
Fiber,
|
|
||||||
typed_data::Inspect,
|
|
||||||
value::{self, Opaque},
|
|
||||||
};
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
ecs::{component::Component, entity::Entity, resource::Resource, schedule::ScheduleLabel},
|
ecs::{component::Component, entity::Entity, resource::Resource, schedule::ScheduleLabel},
|
||||||
|
|
@ -24,7 +19,7 @@ use magnus::{
|
||||||
value::{Lazy, ReprValue},
|
value::{Lazy, ReprValue},
|
||||||
};
|
};
|
||||||
use magnus::{method, prelude::*};
|
use magnus::{method, prelude::*};
|
||||||
use rb_sys::{VALUE, rb_load, ruby_init_stack};
|
use rb_sys::{VALUE, ruby_init_stack};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -179,19 +174,6 @@ fn then(r_self: magnus::Value) -> magnus::Value {
|
||||||
.into_value()
|
.into_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn await_promise(r_self: magnus::Value) -> magnus::Value {
|
|
||||||
let promise: &Promise<(), RubyValue> =
|
|
||||||
TryConvert::try_convert(r_self).expect("Couldn't convert self to Promise");
|
|
||||||
let ruby =
|
|
||||||
Ruby::get().expect("Failed to get a handle to Ruby API when registering Promise callback");
|
|
||||||
let fiber = Opaque::from(ruby.fiber_current().as_value());
|
|
||||||
if let Some(value) = &promise.inner.try_lock().unwrap().resolved_value {
|
|
||||||
return ruby.get_inner(value.0);
|
|
||||||
}
|
|
||||||
promise.clone().await_promise(RubyValue(fiber)).into_value();
|
|
||||||
ruby.fiber_yield::<_, magnus::Value>(()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[magnus::wrap(class = "Bevy::Entity")]
|
#[magnus::wrap(class = "Bevy::Entity")]
|
||||||
pub struct BevyEntity(pub Entity);
|
pub struct BevyEntity(pub Entity);
|
||||||
|
|
@ -213,19 +195,6 @@ impl TryConvert for BevyEntity {
|
||||||
#[magnus::wrap(class = "Bevy::Vec3")]
|
#[magnus::wrap(class = "Bevy::Vec3")]
|
||||||
pub struct BevyVec3(pub Vec3);
|
pub struct BevyVec3(pub Vec3);
|
||||||
|
|
||||||
pub fn async_function() {
|
|
||||||
let ruby = Ruby::get().unwrap();
|
|
||||||
let fiber = ruby
|
|
||||||
.fiber_new_from_fn(Default::default(), move |ruby, _args, _block| {
|
|
||||||
let p = ruby.block_proc().unwrap();
|
|
||||||
p.call::<_, value::Value>(()).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
fiber.resume::<_, magnus::Value>(()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BevyVec3 {
|
impl BevyVec3 {
|
||||||
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||||
Self(Vec3::new(x, y, z))
|
Self(Vec3::new(x, y, z))
|
||||||
|
|
@ -297,15 +266,12 @@ impl Default for RubyRuntime {
|
||||||
|
|
||||||
let promise = module.define_class("Promise", ruby.class_object())?;
|
let promise = module.define_class("Promise", ruby.class_object())?;
|
||||||
promise.define_method("and_then", magnus::method!(then, 0))?;
|
promise.define_method("and_then", magnus::method!(then, 0))?;
|
||||||
promise.define_method("await", magnus::method!(await_promise, 0))?;
|
|
||||||
|
|
||||||
let vec3 = module.define_class("Vec3", ruby.class_object())?;
|
let vec3 = module.define_class("Vec3", ruby.class_object())?;
|
||||||
vec3.define_singleton_method("new", function!(BevyVec3::new, 3))?;
|
vec3.define_singleton_method("new", function!(BevyVec3::new, 3))?;
|
||||||
vec3.define_method("x", method!(BevyVec3::x, 0))?;
|
vec3.define_method("x", method!(BevyVec3::x, 0))?;
|
||||||
vec3.define_method("y", method!(BevyVec3::y, 0))?;
|
vec3.define_method("y", method!(BevyVec3::y, 0))?;
|
||||||
vec3.define_method("z", method!(BevyVec3::z, 0))?;
|
vec3.define_method("z", method!(BevyVec3::z, 0))?;
|
||||||
|
|
||||||
ruby.define_global_function("async", function!(async_function, 0));
|
|
||||||
Ok::<(), ScriptingError>(())
|
Ok::<(), ScriptingError>(())
|
||||||
}))
|
}))
|
||||||
.expect("Failed to define builtin types");
|
.expect("Failed to define builtin types");
|
||||||
|
|
@ -426,35 +392,10 @@ impl Runtime for RubyRuntime {
|
||||||
) -> Result<Self::ScriptData, crate::ScriptingError> {
|
) -> Result<Self::ScriptData, crate::ScriptingError> {
|
||||||
let script = script.0.clone();
|
let script = script.0.clone();
|
||||||
self.execute_in_thread(Box::new(move |ruby: &Ruby| {
|
self.execute_in_thread(Box::new(move |ruby: &Ruby| {
|
||||||
let p = Opaque::from(ruby.proc_from_fn(move |ruby, _args, _block| {
|
|
||||||
Self::with_current_entity(ruby, entity, || {
|
Self::with_current_entity(ruby, entity, || {
|
||||||
let mut tmpfile = tempfile::NamedTempFile::new().unwrap();
|
ruby.eval::<magnus::value::Value>(&script)
|
||||||
tmpfile.write(script.as_bytes()).unwrap();
|
.map_err(<magnus::Error as Into<ScriptingError>>::into)
|
||||||
unsafe {
|
})?;
|
||||||
let file = rb_sys::rb_str_new_cstr(
|
|
||||||
CString::new(tmpfile.path().to_str().unwrap())
|
|
||||||
.unwrap()
|
|
||||||
.into_raw(),
|
|
||||||
);
|
|
||||||
rb_load(file, 0);
|
|
||||||
};
|
|
||||||
// ruby.eval::<magnus::value::Value>(&script)
|
|
||||||
// .map_err(<magnus::Error as Into<ScriptingError>>::into)
|
|
||||||
Ok::<(), ScriptingError>(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}));
|
|
||||||
let fiber = ruby
|
|
||||||
.fiber_new_from_fn(Default::default(), move |ruby, _args, _block| {
|
|
||||||
let p = ruby.get_inner(p);
|
|
||||||
|
|
||||||
p.call::<_, value::Value>(()).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
fiber.resume::<_, value::Value>(()).unwrap();
|
|
||||||
|
|
||||||
Ok::<Self::ScriptData, ScriptingError>(RubyScriptData)
|
Ok::<Self::ScriptData, ScriptingError>(RubyScriptData)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
@ -568,15 +509,6 @@ impl Runtime for RubyRuntime {
|
||||||
fn needs_rdynamic_linking() -> bool {
|
fn needs_rdynamic_linking() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume(&self, fiber: &Self::Value, value: &Self::Value) {
|
|
||||||
let fiber = fiber.clone();
|
|
||||||
let value = value.clone();
|
|
||||||
self.execute_in_thread(move |ruby| {
|
|
||||||
let fiber: Fiber = TryConvert::try_convert(ruby.get_inner(fiber.0)).unwrap();
|
|
||||||
fiber.resume::<_, magnus::Value>((value.0,));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod magnus {
|
pub mod magnus {
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,6 @@ pub(crate) fn init_callbacks<R: Runtime>(world: &mut World) -> Result<(), Script
|
||||||
move |context, params| {
|
move |context, params| {
|
||||||
let promise = Promise {
|
let promise = Promise {
|
||||||
inner: Arc::new(Mutex::new(PromiseInner {
|
inner: Arc::new(Mutex::new(PromiseInner {
|
||||||
resolved_value: None,
|
|
||||||
fibers: vec![],
|
|
||||||
callbacks: vec![],
|
callbacks: vec![],
|
||||||
context,
|
context,
|
||||||
})),
|
})),
|
||||||
|
|
@ -102,7 +100,7 @@ pub(crate) fn init_callbacks<R: Runtime>(world: &mut World) -> Result<(), Script
|
||||||
.expect("Failed to lock callback calls mutex");
|
.expect("Failed to lock callback calls mutex");
|
||||||
|
|
||||||
calls.push(FunctionCallEvent {
|
calls.push(FunctionCallEvent {
|
||||||
promise: promise.clone(), // TODO: dont clone?
|
promise: promise.clone(),
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
Ok(promise)
|
Ok(promise)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue