makspll / bevy_mod_scripting Goto Github PK
View Code? Open in Web Editor NEWBevy Scripting Plugin
License: Apache License 2.0
Bevy Scripting Plugin
License: Apache License 2.0
bevyengine/bevy#4474 is now closed, for scripting/reflection stuff, discussion has shifted towards https://github.com/orgs/bevyengine/projects/5
Right now errors are printed to the standard output,
It would be preferable to pass errors onto the user for further handlling.
For example, printing lua errors to an in game console
Current CI is extremely slow
I'm trying to get a working example of this running and have found it to be quite difficult, the examples are quite difficult to understand.
also running into this error when I generate a blank project with bevy + bevy_mod_scripting:
error[E0308]: `?` operator has incompatible types
--> /Users/xx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_script_api-0.3.0/src/generated.rs:4266:17
|
4266 | #[languages(on_feature(lua))]
| ^^^^^^^^^^^^^^^ expected `BVec4`, found `BVec4A`
|
= note: `?` operator cannot convert from `BVec4A` to `BVec4`
= note: this error originates in the macro `impl_lua_newtype` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> /Users/xx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_script_api-0.3.0/src/generated.rs:4266:17
|
4266 | #[languages(on_feature(lua))]
| ^^^^^^^^^^^^^^^
| |
| expected `BVec4A`, found `BVec4`
| arguments to this function are incorrect
|
note: associated function defined here
--> /Users/xx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_script_api-0.3.0/src/wrappers.rs:38:16
|
38 | pub fn new(b: $type_) -> Self {
| ^^^ ---------
|
::: /Users/xx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_script_api-0.3.0/src/generated.rs:4770:17
|
4770 | #[languages(on_feature(lua))]
| --------------- in this macro invocation
= note: this error originates in the macro `impl_lua_newtype` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
error: could not compile `bevy_script_api` (lib) due to 2 previous errors
Compiling on the latest stable version rustc 1.70.0 (90c541806 2023-05-31) and I tried on nightly.
I started towards trying to do my own update to bevy 0.12(haven't not noticed the issue here recently that mentioned it being possibly coming soon), and I've found that I can't build from the repo at all now when I use the lua-api and lua54 features. I get a bunch of errors from tealr macros. tealr_derive::TypeName, ToTypename, IntoLua... I'm thinking there's been some poorly-versioned breaking changes up stream but haven't yet found a correct combination of version specifications to get back to buildable.
A breaking change happened either in rustdoc --json or in the bevy docs which removed import paths for many items, as well as their trait implementations, meaning make generate_api
currently breaks.
I'm not sure if this is a problem on my side, though the examples I've tried all seem to fail because two versions of nix
are in use, e.g. when I run this on main
cargo run --example complex_game_loop_lua --features lua54
I get the following error
$ cargo run --example complex_game_loop_lua --features lua54 main@781754a
Compiling syn v1.0.103
Compiling serde v1.0.147
Compiling rand_chacha v0.3.1
Compiling rand v0.8.5
Compiling encase_derive_impl v0.3.0
Compiling toml v0.5.9
Compiling bevy_macro_utils v0.8.1
Compiling serde_derive v1.0.147
Compiling thiserror-impl v1.0.37
Compiling bytemuck_derive v1.2.1
Compiling bevy_reflect_derive v0.8.1
Compiling bevy_ecs_macros v0.8.1
Compiling bevy_derive v0.8.1
Compiling encase_derive v0.3.0
Compiling bevy_encase_derive v0.8.1
Compiling bevy_render_macros v0.8.1
Compiling gltf-derive v1.0.0
Compiling hash32-derive v0.1.1
Compiling tealr_derive v0.9.0-alpha3
Compiling taffy v0.1.0
Compiling bytemuck v1.12.1
Compiling image v0.24.4
Compiling thiserror v1.0.37
Compiling smallvec v1.10.0
Compiling hashbrown v0.12.3
Compiling glam v0.21.3
Compiling uuid v1.2.1
Compiling erased-serde v0.3.23
Compiling serde_json v1.0.87
Compiling ron v0.7.1
Compiling tealr v0.9.0-alpha3
Compiling parking_lot_core v0.9.4
Compiling tracing-subscriber v0.3.16
Compiling parking_lot_core v0.8.5
Compiling parking_lot v0.12.1
Compiling parking_lot v0.11.2
Compiling gilrs-core v0.4.1
Compiling bevy_utils v0.8.1
Compiling indexmap v1.9.1
Compiling gpu-descriptor v0.2.3
Compiling cpal v0.13.5
Compiling winit v0.26.1
Compiling gilrs v0.9.0
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:245:21
|
244 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<host::alsa::alsa::PCM, (host::alsa::alsa::Error, host::alsa::alsa::nix::errno::Errno)>`
245 | Err((_, nix::errno::Errno::EBUSY)) => return Err(BuildStreamError::DeviceNotAvailable),
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:246:21
|
244 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<host::alsa::alsa::PCM, (host::alsa::alsa::Error, host::alsa::alsa::nix::errno::Errno)>`
245 | Err((_, nix::errno::Errno::EBUSY)) => return Err(BuildStreamError::DeviceNotAvailable),
246 | Err((_, nix::errno::Errno::EINVAL)) => return Err(BuildStreamError::InvalidArgument),
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:302:21
|
301 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<&mut host::alsa::alsa::PCM, (host::alsa::alsa::Error, host::alsa::alsa::nix::errno::Errno)>`
302 | Err((_, nix::errno::Errno::ENOENT)) | Err((_, nix::errno::Errno::EBUSY)) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:302:59
|
301 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<&mut host::alsa::alsa::PCM, (host::alsa::alsa::Error, host::alsa::alsa::nix::errno::Errno)>`
302 | Err((_, nix::errno::Errno::ENOENT)) | Err((_, nix::errno::Errno::EBUSY)) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:305:21
|
301 | let handle = match handle_result {
| ------------- this expression has type `std::result::Result<&mut host::alsa::alsa::PCM, (host::alsa::alsa::Error, host::alsa::alsa::nix::errno::Errno)>`
...
305 | Err((_, nix::errno::Errno::EINVAL)) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:720:36
|
720 | Err(err) if err.errno() == nix::errno::Errno::EPIPE => {
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
error[E0308]: mismatched types
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/cpal-0.13.5/src/host/alsa/mod.rs:803:40
|
803 | Err(err) if err.errno() == nix::errno::Errno::EPIPE => {
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `host::alsa::alsa::nix::errno::Errno`, found enum `nix::errno::Errno`
|
= note: enum `nix::errno::Errno` and enum `host::alsa::alsa::nix::errno::Errno` have similar names, but are actually distinct types
note: enum `nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.23.1/src/errno.rs:774:5
|
774 | pub enum Errno {
| ^^^^^^^^^^^^^^
note: enum `host::alsa::alsa::nix::errno::Errno` is defined in crate `nix`
--> /home/darth/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.24.2/src/errno.rs:776:5
|
776 | pub enum Errno {
| ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `nix` are being used?
For more information about this error, try `rustc --explain E0308`.
error: could not compile `cpal` due to 7 previous errors
In testing, using require "common"
with the require feature gets me the output
2023-08-27T22:50:30.267464Z WARN bevy_mod_scripting_core::hosts: Error in loading script AssetPath {
path: "scripts/1.lua",
label: None,
}:
Failed to load script asset for `AssetPath {
path: "scripts/1.lua",
label: None,
}` runtime error: [string "AssetPath {..."]:1: module 'common' not found:
no field package.preload['common']
no file 'D:\Code\luademo\target\debug\lua\common.lua'
no file 'D:\Code\luademo\target\debug\lua\common\init.lua'
no file 'D:\Code\luademo\target\debug\common.lua'
no file 'D:\Code\luademo\target\debug\common\init.lua'
no file 'D:\Code\luademo\target\debug\..\share\lua\5.4\common.lua'
no file 'D:\Code\luademo\target\debug\..\share\lua\5.4\common\init.lua'
no file '.\common.lua'
no file '.\common\init.lua'
no file 'D:\Code\luademo\target\debug\common.dll'
no file 'D:\Code\luademo\target\debug\..\lib\lua\5.4\common.dll'
no file 'D:\Code\luademo\target\debug\loadall.dll'
no file '.\common.dll'
stack traceback:
[C]: in ?
[C]: in function 'require'
[string "AssetPath {..."]:1: in main chunk
common.lua
is in this case sitting in my project's assets\scripts
directory right next to my other lua files, it's actually being loaded by bevy's asset server even. To get it to load I must use require "assets/scripts/common"
(running via cargo from the project root dir)
Ultimately, for my ends I think I want require to load from bevy's asset server somehow as part of a sandboxing effort. That feels potentially out of scope as a core feature, but it seems like this crate should probably at the least add the assets directory to the searcher paths.
Hello, first thank you for this great crate.
I am currently using your project to implement scripting support in a project using bevy. However, I got the following issue:
AssetIO
override that maps the path to a path into a zip fileSo in all loading, the asset server is involved - and that would include loading dependencies.
Now I got the the issue that e.g. a lua snippet wants to run
dofile '/some/path/to/a/script.lua'
and would require to be paused, until the resource is available and the string contents are injected. The lua engine used (Luajit) claims to be fully resumable, so it should be possible to yield across the language barriers, however that exactly is not working with the error:
attempt to yield across C-call boundary
Is there another approach I should take when lua wants to load a resource that involves async loading from the asset server?
The example file for console integration seem out date. I can get part of it working. There not much example of set up the Cargo.toml.
Try work on windows.
[dependencies]
bevy = "0.9"
clap = "4.0.32"
bevy_console = "0.6.0"
bevy_mod_scripting = {version = "0.2.2", features =["lua","lua54"]}
Found the bevy_console has change some set up.
#[derive(Parser, ConsoleCommand)]
#[command(name = "run_script")]
// no method named `get_world` found for reference `&bevy_mod_scripting::prelude::Lua` in the current scope
let world = ctx.get_world()?
//method not found in `&bevy_mod_scripting::prelude::Lua`
//mismatched types
events.send(PrintConsoleLine { line: msg });
//expected struct `clap::builder::StyledStr`, found struct `std::string::String`
There are some area can't figure since wanted to keep it simple. Still learning how to get part example working. Not sure how to config them right.
Two questions:
When I work with scripts in Godot, I attach a script to a node, then export a variable from that script so that that particular script instance has a unique value. While there is no editor, is it possible to encode this data in a scene?
Allow scripts querying for entities with different components.
bevy_ecs_dynamic
Like, really really unsound.
Paraphrasing dtonlnay, an API is unsound if it's possible to break its intended invariants in safe code.
WorldPointer
's stated invariant is:
This pointer does not prevent dangling pointers, i.e. you must ensure the world is not dropped while any world pointers still exist, the world must also not change, from the moment a world pointer is created it must always point to the same world.
This isn't entirely correct, and is also incomplete and trivially broken in safe third-party code. The "you must ensure the world is not dropped while any world pointers still exist" bit implies that it's the pointed-to World that can't be dropped, while it's actually the mutable reference itself that determines the maximum lifetime of a WorldPointer
. Where the World
lives is entirely the purview of the bevy internals, and it may be moved around without warning, thus invalidating any previous references to it. Additionally, since the WorldPointer
creates a second, sharable mutable reference to the World
, it also needs to include the invariant that the original &mut World
may only be used through the WorldPointer
while it's in scope. Otherwise, it would violate Rust's aliasing rules.
The first invariant, that the WorldPointer
must not outlive the &mut World
, is broken as soon as ownership gets passed to another function. Since it's 'static
, nothing stops other functions from squirreling it away somewhere that will outlive the &mut World
. Since it's also Clone
, this isn't even preventable by only passing around reference to it, since callees can simply .clone()
it to get an owned version of it, and then do with that whatever they will. The clone
method should probably be changed to be an unsafe struct method rather than the safe trait method that it currently is. Then, if only references to the WorldPointer
are handed out, the onus is on the callees of the unsafe clone method to ensure that the invariants are upheld.
The second invariant, that the original &mut World
must only be used through the WorldPointer
is, for the most part, only the concern of the original creator of the pointer, since they're the only one who ever has access to the original &mut World
to violate it. So long as the first invariant is upheld, it should be possible to guarantee that the second is also upheld entirely within the scope that the WorldPointer
was created.
As far as current invalid usage goes, I believe that any APIProvider
that stores the world in a script context (both the rhai and lua BevyAPIProvider
s for instance) technically violate this, since there's no way for these providers to "un-setup" the script runtime, and destroy their stored WorldPointer
before the ScriptHost
's handle_events
method returns and invalidates the &mut World
.
I am facing a similar set of errors to #61 with bevy 0.11.2
and bevy_mod_scripting commit 8bf3796 with the lua_script_api
flag enabled
cargo run
Updating git repository `https://github.com/makspll/bevy_mod_scripting`
Compiling bevy_script_api v0.3.0 (https://github.com/makspll/bevy_mod_scripting?rev=8bf3796#8bf37962)
error[E0599]: no variant or associated item named `Pairs` found for enum `LuaMetaMethod` in the current scope
--> /Users/videah/.cargo/git/checkouts/bevy_mod_scripting-66f82db9d3a19d6f/8bf3796/bevy_script_api/src/lua/std.rs:317:45
|
317 | methods.add_meta_method(MetaMethod::Pairs, |ctx, s, _: ()| {
| ^^^^^ variant or associated item not found in `LuaMetaMethod`
error[E0308]: `?` operator has incompatible types
--> /Users/videah/.cargo/git/checkouts/bevy_mod_scripting-66f82db9d3a19d6f/8bf3796/bevy_script_api/src/generated.rs:4501:17
|
4501 | #[languages(on_feature(lua))]
| ^^^^^^^^^^^^^^^ expected `BVec4`, found `BVec4A`
|
= note: `?` operator cannot convert from `BVec4A` to `BVec4`
= note: this error originates in the macro `impl_lua_newtype` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> /Users/videah/.cargo/git/checkouts/bevy_mod_scripting-66f82db9d3a19d6f/8bf3796/bevy_script_api/src/generated.rs:4501:17
|
4501 | #[languages(on_feature(lua))]
| ^^^^^^^^^^^^^^^
| |
| expected `BVec4A`, found `BVec4`
| arguments to this function are incorrect
|
note: associated function defined here
--> /Users/videah/.cargo/git/checkouts/bevy_mod_scripting-66f82db9d3a19d6f/8bf3796/bevy_script_api/src/wrappers.rs:38:16
|
38 | pub fn new(b: $type_) -> Self {
| ^^^ ---------
|
::: /Users/videah/.cargo/git/checkouts/bevy_mod_scripting-66f82db9d3a19d6f/8bf3796/bevy_script_api/src/generated.rs:5050:17
|
5050 | #[languages(on_feature(lua))]
| --------------- in this macro invocation
= note: this error originates in the macro `impl_lua_newtype` (in Nightly builds, run with -Z macro-backtrace for more info)
Some errors have detailed explanations: E0308, E0599.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `bevy_script_api` (lib) due to 3 previous errors
My Cargo.toml looks like this:
[package]
name = "myrrh"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
# Enable a small amount of optimization in debug mode
[profile.dev]
opt-level = 1
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
[profile.dev.package."*"]
opt-level = 3
[dependencies]
bevy = { version = "0.11.2", features = ["dynamic_linking"] }
bevy_mod_scripting = { git = "https://github.com/makspll/bevy_mod_scripting", rev = "8bf3796", version = "0.3.0", features = ["luajit", "teal", "lua_script_api"] }
Using Lua (specifically LuaJIT, I haven't tested the other available versions of Lua), while running a script that looks like this:
function on_update()
print("inside")
end
print("outside")
The behavior is as expected: when the script is loaded and the hook is called for the first time, both outside
and inside
are printed. Any subsequent hook calls result in solely inside
being printed, as it does not re-run the main body of the script. e.g.
outside
inside
inside
inside
...
This behavior is not the same when using Rhai. When using Rhai, running a script that looks like this:
fn on_update() {
print("inside")
}
print("outside")
does not produce the expected output. Instead, the entire script is run when it is loaded, printing both outside
and inside
, as expected. Then, whenever the hook is called, the main body of the script is ran again before it runs the hook, meaning it prints both outside
and inside
again, rather than just inside
as expected. e.g.
outside
inside
outside
inside
outside
inside
...
I believe this behavior is a bug, as it's not obvious it would do this by looking at the code, and also doesn't match the behavior when using Lua.
Probably just a matter of adding the logo file to included files in Cargo.toml, will test and PR later.
I want to expose sort of a plugin system for my bevy app.
and i don't want different plugins to be using the same lua vm for four reasons:
so, when i create a LuaScriptCollection
, i want it to have its own lua vm.
is this possible right now?
also, I am wondering there could be a small Architecture.md
explaining at a high level how this works. I am not familiar with what the terms ScriptHost or ScriptCollection really mean in the abstract concept sense.
Hey,
sorry to bother you. I found you issue post (2021): marinaKollmitz/gazebo_ros_2Dmap_plugin#11
Could you remeber how to use the plugin?
I tried it with simple turtlebot3_world map but it doesn't work.
After step 4, i got 2 files:
But the pgm is not the desire grid map of the turtlbot3 world: https://ibb.co/wNB2HdN
I really appreciate your time. Thank you.
I got following struct:
#[derive(Resource, Reflect, Default, Clone)]
#[reflect(Resource)]
pub struct LobbyListResource {
pub lobbies: Vec<u64>,
}
I register all the needed things to correctly access the vec and loop through it via scripts:
struct HandleLobbyApiProvider;
impl APIProvider for HandleLobbyApiProvider {
type APITarget = Engine;
type ScriptContext = RhaiContext;
type DocTarget = RhaiDocFragment;
fn register_with_app(&self, app: &mut App) {
app.register_foreign_rhai_type::<Vec<u64>>();
}
fn attach_api(
&mut self,
api: &mut Self::APITarget,
) -> Result<(), bevy_mod_scripting::prelude::ScriptError> {
api.register_vec_functions::<u64>();
Ok(())
}
}
With this I can then loop through the lobbies in Rhai like this:
let lobby_list_type = world.get_type_by_name(blablabla::LobbyListResource");
if world.has_resource(lobby_list_type) {
let lobbies = world.get_resource(lobby_list_type).lobbies;
for lobby in lobbies {
print(`lobby: ${lobby}`);
}
}
And this works... as long as the vec is not empty!
When it's empty i get following error and it crashes:
thread 'main' panicked at 'attempt to subtract with overflow', C:\...\.cargo\git\checkouts\bevy_mod_scripting-ff78cea4271e6409\8879577\bevy_script_api\src\common\std.rs:136:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in exclusive system `bevy_mod_scripting_core::systems::script_event_handler<bevy_mod_scripting_rhai::RhaiScriptHost<pgc::modding::ModdedScriptRuntimeArguments>, 0, 10>`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
As I'm only using Rhai, I don't know if this error exists in Lua too.
The current workaround is to just check if the vec is empty before trying to loop through it:
let lobby_list_type = world.get_type_by_name(blablabla::LobbyListResource");
if world.has_resource(lobby_list_type) {
let lobbies = world.get_resource(lobby_list_type).lobbies;
if !lobbies.is_empty() {
for lobby in lobbies {
print(`lobby: ${lobby}`);
}
}
}
Hey there, love the crate. Bevy 0.10 does away with stages in favour of system sets - is there any plan to update this library to support this?
This crate should be updated to support Bevy v0.9
I despawn an entity (recursively) that has a script attached to it. but the script still "exists" and receives the events.
I'm currently only working with the Rhai implementation, so idk if this is a general problem or not. but its definitely not what i expect it to work like XD
Current macros are very ugly, written before I had a full grasp of the capabilities of rust meta-programming,
I intend to make things like these possible:
#[derive(ScriptProxy, Reflect)]
#[proxy(languages("on_feature(lua)"))]
#[functions[
#[lua(MutatingMetaMethod)]
fn basd(mut self) {
}
#[lua(MetaMethod)]
fn asd(self);
#[lua(Function)]
fn basda(self);
]]
pub struct Lol {}
Hi!
Could be that I completely misunderstand events in this crate.
I've implemented a function that allows me to spawn a mod.
So via script, i can just spawn other mods.
and those spawned mods then get called the "on_init" function in their script!
problem is, as soon as there is more than just one at the same time, only one of them gets the init method called.
same thing for the Update call.
I can't use Recipients::All because i need to do some additional checks before calling on_update on that entity, so i use Recipient::Entity, and loop through all of them. and here the same problem!
Am I misunderstanding something or is this a "design flaw"?
Noticed that this is a bug in the rhai implementation. Lua did not behave Like this.
I saw #62 for bevy 0.11 support, and it looks like bevy 0.12 was released a couple of weeks ago. I'm starting a new project where I'll lock into a certain version of bevy.
Given the last release in May covered bevy 0.10, should I leverage bevy 0.11 or bevy 0.12 in anticipation for the next release of this crate? I'm brand new, so I don't (and shouldn't) have much weight in the decision here. Just want to know if there are plans/expectations for one version over the other! ๐
I'd toss this into a discussion instead of an issue, but looks like discussions aren't enabled for this repository. So apologies if this clutters the issue section!
I've cloned the repository locally and tried to run the wrappers example from it with cargo run --example wrappers --features="lua lua54 lua_script_api"
. I get this result after the initial startup info line
ERROR bevy_mod_scripting_lua: Runtime error in script `script.lua` callback error
stack traceback:
[C]: in field 'make_ref_to_my_resource'
[string "script.lua"]:3: in function 'once'
caused by: error converting Lua nil to userdata
After script run: MyThing {
usize: 420,
string: "I live in the bevy world, you can't touch me!",
}
I've tried this test on both the main branch and the 0.11 branch with the same result
If I read the code correctly, I believe it's supposed to error in the second script run, but not the first. It appears that the issue comes from
fn "make_ref_to_my_resource" => |ctx,()| {
let globals = ctx.globals();
let lua_world : LuaWorld = globals.("world")?; //This lineA
I changed it to
let lua_world_o = globals.get("world");
info!("{:#?}",lua_world_o);
let lua_world :LuaWorld = lua_world_o.unwrap();
and got
wrappers:
INFO wrappers: Err(
FromLuaConversionError {
from: "nil",
to: "userdata",
message: None,
},
)
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: FromLuaConversionError { from: "nil", to: "userdata", message: None }', examples/wrappers.rs:69:52
)
Getting access to the world like this is really the thing I need most out of the crate right now, so any help would be very appreciated.
I would like to implement a ScriptHost for Gluon.
Is there any contributing rules or conventions that I should be aware of?
Gluon is a small, statically-typed, functional programming language designed for application embedding.
Ability to send events to a subset of scripts, currently is not supported
So far I am the only committed maintainer of this crate. This has worked very well when I didn't have any other major responsibilities, but since getting a full time job, I've been struggling to keep the updates coming.
Do not be scared, I am not pausing development or anything of the sort, I will eventually be able to fall back into the rhythm and keep improving the crate. In fact I am looking forward to a big re-write when dynamic systems are possible in Bevy!
Having additional maintainers would mean a much more predictable release cycle, and at the very least keeping up with the Bevy train on time.
At the beginning, this library was just a single crate, and everything was simple. Then the scope increased, and suddenly I was supporting an ever changing bevy scripting API, which is still unfinished, as well as keeping up with a multitude of tools including tealr
, teal
, rhai
etc..
The library reached the point where coming back to it after long breaks means re-discovering all the design choices I have made. This means that new people joining the project wouldn't be far behind me in understanding everything ;)
At the very least I am looking for a dedicated person able to commit to keeping this crate updated whenever Bevy changes (which usually isn't that much work), so I can focus on improving the library. Ideally we'd have more people, a subject matter expert for every language we support, and maybe some people dedicated to other bits and bobs (like docs, optimisation etc..). I am aware this might be a bit much considering the library isn't that popular, but one can hope :)
If you're at all interested in using this crate, and would like to contribute, reach out to me over at [email protected], nothing formal, just tell me about yourself, how you use this library and/or how/to what extent you'd like to help out! Alternatively use this google form: https://forms.gle/vTQnrj2nf8e4n97F9 if that's more your speed!
I'd also love to thank everybody who helped out in the past again (in no particular order)!
Code contributions:
Issue contributions (yes these matter too!):
Every issue, line of code, and piece of grammar checking helps!
Hi, love this crate!
I just came across a small issue.
I need to send out PriorityEvents from a rust function that is registered as a script function.
So it has only access to the ScriptWorld.
With the Normal Bevy Events I can just use world.send_event().
But I can't seem to figure out how to send out priority events with only having the ScriptWorld.
Did I miss anything?
I'm not sure if this is a FR or something else, but here goes.
In my testing I've found global state isn't behaving how I expect Lua state in a game to act. It appears that each script runs inside it's own, enviroment/context. A global defined by one script is nil when another script tries to access it. I can see some cases for this, but it also seems to inhibit many of the approaches to scripting that I want to enable unless I go through a lot of effort to essentially reimplement parts of Lua as resources.
Perhaps relatedly, when a script is reloaded the original global state seems to be discarded and a fresh one replaces it. for instance this hook:
function on_level()
if type(_G.i) == 'nil' then _G.i = 0 end
if(i%200 == 0) then
print("\n******** " .. i )
end
i=i+1
end
In theory the count should persist between reloads, if there was a single context and the hook function was simply replaced by executing the changed file. It appears that it's a clean new context though. Any stateful gameplay scripting live development is going to be really awkward this way. If I make use of require
then it may be viable to code around this to a limited degree inside lua itself, but I'm not sure that can cover everything.
Do you think it'd be feasible for a game to get around either of those with custom ScriptHost implementations? If not, is it conceivable to make those alternate behaviors available somehow, likely optionally? I've only got a loose grasp of the internals of the crate so far, so I'm not able to make a confident guess myself.
I'm reading examples to understand how exactly can I use this crate for my project. So far it wasn't very easy to understand, I had to go back and forth: exampels, script assets, API docs. And also I don't understand some comments completely, like this one. It looks like it's out of place.
This is why I think exampels need improvements to the explanation comments and more such comments.
Features every script should have access to, i.e.:
Lua API has been completed with a general framework extendable by other languages. Rhai will be supported in another release
Currently latest version availableon docs.rs is 0.1.2. All other versions fail to build with an error that is caused by some required features not being enabled.
Also duplicating the full text here:
# rustc version
rustc 1.68.0-nightly (0b90256ad 2023-01-13)
# docs.rs version
docsrs 0.6.0 (19c77a92 2023-01-08)
# build log
[INFO] running `Command { std: "docker" "create" "-v" "/home/cratesfyi/workspace/builds/bevy_mod_scripting-0.2.2/target:/opt/rustwide/target:rw,Z" "-v" "/home/cratesfyi/workspace/builds/bevy_mod_scripting-0.2.2/source:/opt/rustwide/workdir:ro,Z" "-v" "/home/cratesfyi/workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/home/cratesfyi/workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "DOCS_RS=1" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "3221225472" "--cpus" "3" "--user" "1001:1001" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:9042d5c95763f71f7b0904716b98ccadf9fc47b0f382ee962aaaed2ac70c9b8d" "/opt/rustwide/cargo-home/bin/cargo" "+nightly" "rustdoc" "--lib" "-Zrustdoc-map" "--features" "lua rhai lua_script_api rhai_script_api teal" "-Z" "unstable-options" "--config" "build.rustdocflags=[\"-Z\", \"unstable-options\", \"--emit=invocation-specific\", \"--resource-suffix\", \"-20230113-1.68.0-nightly-0b90256ad\", \"--static-root-path\", \"/-/rustdoc.static/\", \"--cap-lints\", \"warn\", \"--disable-per-crate-search\", \"--extern-html-root-takes-precedence\"]" "--offline" "-Zunstable-options" "--config=doc.extern-map.registries.crates-io=\"https://docs.rs/{pkg_name}/{version}/x86_64-unknown-linux-gnu\"" "-Zrustdoc-scrape-examples" "-j3" "--target" "x86_64-unknown-linux-gnu", kill_on_drop: false }`
[INFO] [stdout] 174db56665a4e7c628ba6a7b5cf800ee417f0556e9d9af23b34586d031af6fc0
[INFO] [stderr] WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
[INFO] running `Command { std: "docker" "start" "-a" "174db56665a4e7c628ba6a7b5cf800ee417f0556e9d9af23b34586d031af6fc0", kill_on_drop: false }`
[INFO] [stderr] warning: Rustdoc did not scrape the following examples because they require dev-dependencies: console_integration_lua, console_integration_rhai, complex_game_loop_lua, game_of_life_lua, game_of_life_rhai, event_recipients_lua, coroutines_lua, documentation_gen_lua, bevy_api_lua, bevy_api_rhai, wrappers
[INFO] [stderr] If you want Rustdoc to scrape these examples, then add `doc-scrape-examples = true`
[INFO] [stderr] to the [[example]] target configuration of at least one example.
[INFO] [stderr] warning: Target filter specified, but no targets matched. This is a no-op
[INFO] [stderr] Checking bevy_ui v0.9.1
[INFO] [stderr] Compiling mlua v0.8.7
[INFO] [stderr] Compiling rustls v0.20.8
[INFO] [stderr] error: You must enable one of the features: lua54, lua53, lua52, lua51, luajit, luajit52, luau
[INFO] [stderr] --> /opt/rustwide/cargo-home/registry/src/github.com-1ecc6299db9ec823/mlua-0.8.7/build/main.rs:52:5
[INFO] [stderr] |
[INFO] [stderr] 52 | / compile_error!(
[INFO] [stderr] 53 | | "You must enable one of the features: lua54, lua53, lua52, lua51, luajit, luajit52, luau"
[INFO] [stderr] 54 | | );
[INFO] [stderr] | |_____^
[INFO] [stderr]
[INFO] [stderr] error: could not compile `mlua` due to previous error
[INFO] [stderr] warning: build failed, waiting for other jobs to finish...
[INFO] running `Command { std: "docker" "inspect" "174db56665a4e7c628ba6a7b5cf800ee417f0556e9d9af23b34586d031af6fc0", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "174db56665a4e7c628ba6a7b5cf800ee417f0556e9d9af23b34586d031af6fc0", kill_on_drop: false }`
[INFO] [stdout] 174db56665a4e7c628ba6a7b5cf800ee417f0556e9d9af23b34586d031af6fc0
Hi, I see your comment on "Rhai currently does not have any utilities existing for generating documentation (for the rust provided API), once something comes out we'll include it."
May I point you to the metadata
feature which provides metadata (including comments) on Rust/Rhai functions: https://rhai.rs/book/engine/metadata/index.html
Now that the foundational work is done the Rhai API can be written as well, the work needed is as follows:
bevy_mod_scripting_derive
which generates Rhai<Type>
Wrappers similarly to the Lua implementorLuaProxyable
ToLuaProxy
and FromLuaProxy
To promote compartmentalisation, Rhai and Lua should be in their own crates in this repo, they should also be opt-in instead of provided by default to speed up compilation when they are not necessary
Trying to build this project causes a compile error: https://gist.github.com/JohnTheCoolingFan/3e4ae02a70dcd94d6925dbdc73e4832e
Filed an issue at tealr
repo as well: lenscas/tealr#80
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.
The crate is very new, and I am not that familiar with Rust + Bevy,
Baseline benchmarks should be written, and code optimised.
A good start would be, not running scripts which do not have any callbacks corresponding to the set of events fired this frame.
original discussion in #12
It is quite important to minimize the size of this structure, since it's widely used,created and passed around, Ideally this should be a Copy type
I get a compiler error due to a bug in generated.rs
:
Compiling bevy_mod_scripting v0.1.1
error[E0283]: type annotations needed
--> C:\Users\HP\.cargo\registry\src\mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd\bevy_mod_scripting-0.1.1\src\api\generated.rs:9197:39
|
9197 | instances.add_instance("Name".into(), tealr::mlu::UserDataProxy::<LuaName>::new)?;
| ------------ ^^^^
| required by a bound introduced by this call
|
= note: cannot satisfy `_: Into<Cow<'static, str>>`
note: required by a bound in `add_instance`
--> C:\Users\HP\.cargo\registry\src\mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd\tealr-0.9.0-alpha3\src\mlu\teal_data_methods.rs:107:12
|
107 | P: Into<Cow<'static, str>>,
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `add_instance`
help: try using a fully qualified path to specify the expected types
|
9197 | instances.add_instance(<&str as Into<T>>::into("Name"), tealr::mlu::UserDataProxy::<LuaName>::new)?;
| ++++++++++++++++++++++++ ~
After I manually resplaced all instances.add_instance("xxx".into() , tealr::mlu::UserDataProxy::<LuaName>::new)
with instances.add_instance("xxx", tealr::mlu::UserDataProxy::<LuaName>::new)
, it successfully complied.
Here are my dependencies:
[dependencies]
rand = "0.8.5"
bevy = { version = "0.8.0", features = ["dynamic"] }
bevy-inspector-egui = "0.13.0"
bevy_mod_scripting = { version = "0.1.1", features = ["lua54", "mlua_macros", "mlua_serialize", "unsafe_lua_modules"]}
As touched on in #65 I have a little demo project that I've been using for prototyping, and it encapsulates both my expected usage and my hacks in service of #65 and #69 pretty well. That project is now public at https://github.com/LaserWitch/lw_bevy_lua_demo. The code is rough in spots, and probably the documenting too, but it currently checks all the boxes I expect to need checked for my game project. Any pointers for improvement or other thoughts on it would be useful, and anything that can be made a crate feature you're welcome to lift of course.
After working with it a bit, the provided bevy API is surprisingly solid in many ways. I originally expected to need to do more work myself when it came to providing direct access to fields on components. My thoughts on potential areas of improvement might show in where I wrote helpers, but I'll try to think of them now...
(Vec3)
component that's Deref and DerefMut, and if memory serves I needed to do v.1
in lua to get at it's components at all. That surprised me.length()
reported it one element shorter than it actually was.world
methods without conflict...That's what I can recall right now!
So this is more of a general feature request/enhancement (also a question), but something that would be extremely useful in my use cases would be having a task scheduler so that scripts could, for example, yield back to the engine for a specified duration (like a sleep
function). This could also potentially be used for calling callback functions bound to specific events through functions, rather than having specific hook functions.
An example of this might look like this:
-- another benefit of this is having multiple callbacks defined per script
physics_stepped_event:bind(function()
-- do something
sleep(5) -- sleep for 5 seconds
-- do something else
end)
Rather than the current hook-based system:
-- it's a hook so it can only be defined once per script
function physics_stepped_event()
-- do something
-- no idea how you'd wait here, maybe call a function and pass the name of another hook to call as well as the time to sleep?
end
I do know this isn't currently possible with the current language implementations, but could something like this be implemented on top of the existing traits? I do know the current system probably works better under Bevy's ECS system, but for me the benefits from having this outweighs the extra work I'd have to do to create the necessary APIs.
It's something that would be extremely useful for my projects, and would be something I would consider implementing myself as well (and of course I'd be willing to consider submitting a PR if you think it'd be a worthy addition). I just don't know enough about how the code is structured to know if I could implement this on top of it or not.
Tealr now supports custom templating in documentation generation. With that newfound power we should upgrade the template
Following scenario, i get a resource
let lobby_list_type = world.get_type_by_name("blablabla::LobbyListResource");
if world.has_resource(lobby_list_type) {
let lobby_list = world.get_resource(lobby_list_type);
print(`lobby list type: ${type_of(lobby_list)}, lobby list: ${lobby_list}`);
}
This resource looks like this:
#[derive(Resource, Reflect, Default, Clone)]
#[reflect(Resource)]
pub struct LobbyListResource(pub Vec<u64>);
Quite simple.
I now want to access the different lobbies from the vec, I figured out that I can just access them by indexing.
print(`lobby list: ${lobby_list[0]}`);
this works.
But I'd like to loop through them:
for lobby in lobby_list {
print(`lobby: ${lobby}`);
}
Which gives me following error: Runtime error in script "script_name.rhai" For loop expects iterable type
.
So I looked into Rhai and how you've implemented some things.
For example, I can use the api.build_type
in the attach_api
of an APIProvider, and register some functions as well as it being iterable:
#[derive(Resource, Reflect, Default, Clone)]
#[reflect(Resource)]
pub struct LobbyListResource(pub Vec<u64>);
impl IntoIterator for LobbyListResource {
type Item = u64;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl CustomType for LobbyListResource {
fn build(mut builder: rhai::TypeBuilder<Self>) {
builder
.with_name("LobbyListResource")
.with_indexer_get(LobbyListResource::get_field).is_iterable();
}
}
struct HandleLobbyApiProvider;
impl APIProvider for HandleLobbyApiProvider {
type APITarget = Engine;
type ScriptContext = RhaiContext;
type DocTarget = RhaiDocFragment;
fn attach_api(
&mut self,
api: &mut Self::APITarget,
) -> Result<(), bevy_mod_scripting::prelude::ScriptError> {
api.build_type::<LobbyListResource>();
Ok(())
}
}
But that doesn't solve my problem, because the script only gets a ReflectedValue. So i'm wondering if there is a way for me to turn a ReflectedValue into a specific Type?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.