bevy_mod_js_scripting is an experimental scripting integration crate for writing javascript/typescript scripts and running them
in bevy with full access to the ECS values like components and resources.
Example
// type safe access to resources and values
type Scoreboard = { score: number };
const Scoreboard: BevyType<Scoreboard> = { typeName: "breakout::Scoreboard" };
// script-local variables can be used for easy cross-frame state
let i = 0;
function run() {
// increment score every 60 frames
if(i % 60 == 0) {
let score = world.resource(Scoreboard)!;
score.score += 1;
// logging works via `trace`, `debug`, `info`, `warn`, `error`
info(score.score);
}
// query components
for (const item of world.query(Transform, Aabb)) {
let [transform, aabb] = item.components;
info("Translation:", transform.translation.toString());
info("AABB Center:", aabb.center.toString());
// call methods on value references (requires app code setup, see headless.rs)
let normalized = transform.scale.normalize();
}
}
export default {
// execute the `run` function in the update stage
update: run,
}
More examples can be found in the examples folder.
Also check out the punchy wiki page on scripting, which uses bevy_mod_js_scripting.
Current Status
Currently supported operations are
resource access (world.resource(Time))
world information (world.components, world.resources, world.entities)
dealing with ecs value references (Value.create, Value.patch)
Design decisions
Types
In `bevy_ecs`, the common methods for dealing with ECS values all take a type parameter, like
```rs
world.resource::(); // or
world.query<(Entity, &Component)>();
```
Ideally we would be able to write
```ts
let time = world.resourceJavascript Values & ECS Value references
When you call `world.resource` (or any other method returning references to ECS values), what you get is not just a simple javascript object corresponding to the rust value, but instead a `Proxy` which defers all accesses/modifications to the actual value inside the bevy world.
Only leaf values, like `transform.translation.x`, which can be natively represented as a javascript primitive, are automatically converted to/from the rust representation on gets and sets.
This means that
```ts
let transform = world.resource(Transform);
let translation = transform.translation;
// typeof translation.x == "number"
translation.x = 3.0;
```
If you want to create a new value reference, for example for inserting a new resource, the current APIs to do that are `Value.create` and `Value.patch`.
```ts
let transform = Value.create(Transform);
let vec3 = Value.create(Vec3, { x: 0.0, y: 1.0, z: 2.0 });
transform.translation = vec3;
world.insertResource(Transform, transform);
```
Expect to see changes in this area as we figure out the best way to deal with the interaction of javascript objects and value references.
Web support
bevy_mod_js_scripting can run in the browser using its native javascript execution environment.
To try it out, download and configure wasm-server-runner and run
cargo run --example breakout --target wasm32-unknown-unknown