Skip to content
Merged
13 changes: 9 additions & 4 deletions assets/scripts/breakout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,22 @@ function run() {
if (i % 60 == 0) {
let score = world.resource(Scoreboard)!;
score.score += 1;
info(score.score);
// info(score.score);
}

let input = world.resource(Input(KeyCode))!;
let pressed = input.get_pressed();
info(pressed.toString());
// let input = world.resource(Input(KeyCode))!;
// let pressed = input.get_pressed();
// info(pressed.toString());


if (firstIteration) {
firstIteration = false;

// let value = Value.create(Transform, {
// translation: { x: 5.0, y: 2.0 }
// });
// info(value.toString());

/*for (const item of world.query(Transform, Velocity)) {
let [transform, velocity] = item.components;

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod transpile;
use asset::JsScriptLoader;
use bevy::{asset::AssetStage, prelude::*, utils::HashSet};

pub use bevy_reflect_fns;
pub use asset::JsScript;
pub use bevy_ecs_dynamic;
pub use runtime::{
Expand Down
44 changes: 44 additions & 0 deletions src/runtime/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ fn op_bevy_mod_js_scripting(
args: serde_json::Value,
) -> Result<serde_json::Value, AnyError> {
with_state(state, |state, custom_op_state| {
let args = convert_safe_ints(args);
let script_info = state.borrow::<ScriptInfo>();
let ops = state.borrow::<Ops>();
let op_names = state.borrow::<OpNames>();
Expand Down Expand Up @@ -352,3 +353,46 @@ fn with_state<T: 'static, R, F: FnOnce(&mut OpState, &mut T) -> R>(state: &mut O

r
}

/// Takes a [`serde_json::Value`] and converts all floating point number types that are safe
/// integers, to integers.
///
/// This is important for deserializing numbers to integers, because of the way `serde_json` handles
/// them.
///
/// For example, `serde_json` will not deserialize `1.0` to a `u32` without an error, but it will
/// deserialize `1`. `serde_v8` seems to retun numbers with a decimal point, even when they are
/// valid integers, so this function makes the conversion of safe integers back to integers without
/// a decimal point.
fn convert_safe_ints(value: serde_json::Value) -> serde_json::Value {
match value {
serde_json::Value::Number(n) => {
let max_safe_int = (2u64.pow(53) - 1) as f64;

serde_json::Value::Number(if let Some(f) = n.as_f64() {
if f.abs() <= max_safe_int && f.fract() == 0.0 {
if f == 0.0 {
serde_json::Number::from(0u64)
} else if f.is_sign_negative() {
serde_json::Number::from(f as i64)
} else {
serde_json::Number::from(f as u64)
}
} else {
n
}
} else {
n
})
}
serde_json::Value::Array(arr) => {
serde_json::Value::Array(arr.into_iter().map(|x| convert_safe_ints(x)).collect())
}
serde_json::Value::Object(obj) => serde_json::Value::Object(
obj.into_iter()
.map(|(k, v)| (k, convert_safe_ints(v)))
.collect(),
),
other => other,
}
}
21 changes: 17 additions & 4 deletions src/runtime/ops/ecs/ecs.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
default:
const collected = collectedQuery(target);
const prop = collected[propName];
return prop.bind ? prop.bind(collected) : prop;
return prop && prop.bind ? prop.bind(collected) : prop;
}
}
})
Expand All @@ -98,6 +98,10 @@
Value.unwrapValueRef(value)
);
}

spawn() {
return Value.wrapValueRef(bevyModJsScriptingOpSync("ecs_entity_spawn"));
}
}

const VALUE_REF_GET_INNER = Symbol("value_ref_get_inner");
Expand All @@ -107,7 +111,16 @@
unwrapValueRef(valueRefProxy) {
if (valueRefProxy === null || valueRefProxy === undefined) return valueRefProxy;
const inner = valueRefProxy[VALUE_REF_GET_INNER]
return inner ? inner : valueRefProxy;
if (inner) {
return inner;
} else {
if (typeof valueRefProxy == 'object') {
for (const key of Reflect.ownKeys(valueRefProxy)) {
valueRefProxy[key] = Value.unwrapValueRef(valueRefProxy[key]);
}
}
return valueRefProxy;
}
},

// keep primitives, null and undefined as is, otherwise wraps the object
Expand Down Expand Up @@ -161,7 +174,7 @@
"ecs_value_ref_set",
target.valueRef,
p,
value
Value.unwrapValueRef(value)
);
},
apply: (target, thisArg, args) => {
Expand All @@ -180,7 +193,7 @@

// Instantiates the default value of a given bevy type
create(type, patch) {
return Value.wrapValueRef(bevyModJsScriptingOpSync("ecs_value_ref_default", type, patch));
return Value.wrapValueRef(bevyModJsScriptingOpSync("ecs_value_ref_default", type, Value.unwrapValueRef(patch)));
},

patch(value, patch) {
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/ops/ecs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::runtime::{JsRuntimeOp, OpMap};

use self::types::{JsReflectFunctions, JsValueRefs};

mod component;
mod info;
mod query;
mod resource;
pub mod types;
mod value;
mod world;

pub fn insert_ecs_ops(ops: &mut OpMap) {
ops.insert("ecs.js", Box::new(EcsJs));
Expand Down Expand Up @@ -41,9 +41,11 @@ pub fn insert_ecs_ops(ops: &mut OpMap) {
);
ops.insert("ecs_value_ref_patch", Box::new(value::ecs_value_ref_patch));
ops.insert("ecs_value_ref_cleanup", Box::new(value::EcsValueRefCleanup));
ops.insert("ecs_entity_spawn", Box::new(world::ecs_entity_spawn));
ops.insert("ecs_value_ref_cleanup", Box::new(value::EcsValueRefCleanup));
ops.insert(
"ecs_component_insert",
Box::new(component::ecs_component_insert),
Box::new(world::ecs_component_insert),
);
}

Expand Down
Loading