Skip to content

Commit 691b02b

Browse files
committed
Fix some tests
1 parent 9022289 commit 691b02b

27 files changed

+226
-73
lines changed

crates/bevy_mod_scripting_core/src/bindings/query.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ use std::{any::TypeId, ops::Deref, sync::Arc};
1313
pub struct ScriptTypeRegistration {
1414
pub(crate) registration: Arc<TypeRegistration>,
1515
pub component_id: Option<ComponentId>,
16+
pub resource_id: Option<ComponentId>,
1617
}
1718

1819
impl ScriptTypeRegistration {
19-
pub fn new(registration: Arc<TypeRegistration>, component_id: Option<ComponentId>) -> Self {
20+
pub fn new(
21+
registration: Arc<TypeRegistration>,
22+
component_id: Option<ComponentId>,
23+
resource_id: Option<ComponentId>,
24+
) -> Self {
2025
Self {
2126
registration,
2227
component_id,
28+
resource_id,
2329
}
2430
}
2531

@@ -38,6 +44,7 @@ impl ScriptTypeRegistration {
3844
self.registration.type_info().type_id()
3945
}
4046

47+
/// Returns the [`ComponentId`] for this type, if it is a component or a resource.
4148
#[inline(always)]
4249
pub fn component_id(&self) -> Option<ComponentId> {
4350
self.component_id

crates/bevy_mod_scripting_core/src/bindings/reference.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,33 @@ pub struct ReflectReference {
5656
pub reflect_path: Vec<ReflectionPathElem>,
5757
}
5858

59-
// just a dummy standin for unregistered types
60-
struct UnregisteredType;
59+
6160

6261
impl ReflectReference {
62+
63+
/// If this is a reference to something with a length accessible via reflection, returns that length.
64+
pub fn len(&self, world: &WorldAccessGuard) -> Option<usize> {
65+
world.with_resource(|world, type_registry: Mut<AppTypeRegistry>| {
66+
world.with_resource(|world, allocator: Mut<ReflectAllocator>| {
67+
let type_registry = type_registry.read();
68+
self
69+
.with_reflect(world, &type_registry, Some(&allocator), |r| {
70+
match r.reflect_ref() {
71+
bevy::reflect::ReflectRef::Struct(s) => Some(s.field_len()),
72+
bevy::reflect::ReflectRef::TupleStruct(ts) => Some(ts.field_len()),
73+
bevy::reflect::ReflectRef::Tuple(t) => Some(t.field_len()),
74+
bevy::reflect::ReflectRef::List(l) => Some(l.len()),
75+
bevy::reflect::ReflectRef::Array(a) => Some(a.len()),
76+
bevy::reflect::ReflectRef::Map(m) => Some(m.len( )),
77+
bevy::reflect::ReflectRef::Set(s) => Some(s.len()),
78+
bevy::reflect::ReflectRef::Enum(e) => Some(e.field_len()),
79+
bevy::reflect::ReflectRef::Opaque(_) => None,
80+
}
81+
})
82+
})
83+
})
84+
}
85+
6386
pub fn new_allocated<T: PartialReflect>(
6487
value: T,
6588
allocator: &mut ReflectAllocator,

crates/bevy_mod_scripting_core/src/bindings/world.rs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl WorldCallbackAccess {
170170
world.remove_component(entity, registration)
171171
}
172172

173-
pub fn get_resource(&self, resource_id: ComponentId) -> ScriptResult<ReflectReference> {
173+
pub fn get_resource(&self, resource_id: ComponentId) -> ScriptResult<Option<ReflectReference>> {
174174
let world = self.read().unwrap_or_else(|| panic!("{STALE_WORLD_MSG}"));
175175
world.get_resource(resource_id)
176176
}
@@ -290,10 +290,11 @@ impl<'w> WorldAccessGuard<'w> {
290290

291291
/// Gets the component id of the given component or resource
292292
pub fn get_component_id(&self, id: TypeId) -> Option<ComponentId> {
293-
let components = self.cell.components();
294-
components
295-
.get_id(id)
296-
.or_else(|| components.get_resource_id(id))
293+
self.cell.components().get_id(id)
294+
}
295+
296+
pub fn get_resource_id(&self, id: TypeId) -> Option<ComponentId> {
297+
self.cell.components().get_resource_id(id)
297298
}
298299

299300
/// Checks nobody else is currently accessing the world, and if so locks access to it until
@@ -609,6 +610,7 @@ impl<'w> WorldAccessGuard<'w> {
609610
ScriptTypeRegistration::new(
610611
Arc::new(registration.clone()),
611612
world.get_component_id(registration.type_id()),
613+
world.get_resource_id(registration.type_id()),
612614
)
613615
})
614616
})
@@ -733,27 +735,21 @@ impl<'w> WorldAccessGuard<'w> {
733735
Ok(())
734736
}
735737

736-
pub fn get_resource(&self, resource_id: ComponentId) -> ScriptResult<ReflectReference> {
737-
let component_info = self
738-
.cell
739-
.components()
740-
.get_info(resource_id)
741-
.ok_or_else(|| {
742-
ScriptError::new_runtime_error(format!(
743-
"Resource does not exist: {:?}",
744-
resource_id
745-
))
746-
})?;
738+
pub fn get_resource(&self, resource_id: ComponentId) -> ScriptResult<Option<ReflectReference>> {
739+
let component_info = match self.cell.components().get_info(resource_id) {
740+
Some(info) => info,
741+
None => return Ok(None),
742+
};
747743

748-
Ok(ReflectReference {
744+
Ok(Some(ReflectReference {
749745
base: ReflectBaseType {
750746
type_id: component_info
751747
.type_id()
752748
.expect("Resource does not have type id"),
753749
base_id: ReflectBase::Resource(resource_id),
754750
},
755751
reflect_path: Default::default(),
756-
})
752+
}))
757753
}
758754

759755
pub fn remove_resource(&self, registration: ScriptTypeRegistration) -> ScriptResult<()> {
@@ -772,7 +768,9 @@ impl<'w> WorldAccessGuard<'w> {
772768
}
773769

774770
pub fn has_resource(&self, resource_id: ComponentId) -> bool {
775-
self.cell.components().get_info(resource_id).is_some()
771+
// Safety: we are not reading the value at all
772+
let res_ptr = unsafe { self.cell.get_resource_by_id(resource_id) };
773+
res_ptr.is_some()
776774
}
777775

778776
pub fn get_children(&self, entity: Entity) -> ScriptResult<Vec<Entity>> {
@@ -1520,6 +1518,7 @@ mod test {
15201518
WorldCallbackAccess::with_callback_access(&mut world, |world| {
15211519
let comp_ref = world
15221520
.get_resource(TestResource::test_component_id())
1521+
.unwrap()
15231522
.unwrap();
15241523
assert_eq!(
15251524
comp_ref,
@@ -1542,13 +1541,9 @@ mod test {
15421541
WorldCallbackAccess::with_callback_access(&mut world, |world| {
15431542
let comp_ref = world.get_resource(fake_comp);
15441543
match comp_ref {
1545-
Ok(_) => panic!("Expected error"),
1546-
Err(e) => {
1547-
assert_eq!(e.kind, ScriptErrorKind::RuntimeError);
1548-
assert_eq!(
1549-
e.reason.to_string(),
1550-
format!("Resource does not exist: {fake_comp:?}")
1551-
)
1544+
Ok(None) => {}
1545+
e => {
1546+
panic!("Expected ok with none, got: {:?}", e);
15521547
}
15531548
}
15541549
});

crates/languages/bevy_mod_scripting_lua/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ smallvec = "1.13"
5757
[dev-dependencies]
5858
test_utils = { workspace = true }
5959
libtest-mimic = "0.8"
60+
regex = "1.11"
6061

6162
[[test]]
6263
name = "lua_tests"

crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ use super::{
2929
pub struct LuaReflectReference(pub ReflectReference);
3030

3131
impl LuaReflectReference {
32+
pub fn len(&self, lua: &Lua) -> Result<Option<usize>, mlua::Error> {
33+
let world = lua.get_world()?;
34+
Ok(self.0.len(&world))
35+
}
36+
3237
/// Queries the reflection system for a proxy registration for the underlying type.
3338
/// If found will convert to lua using this proxy
3439
/// If not found will use <Self as [`IntoLua`]>::into_lua to convert to lua
@@ -117,13 +122,6 @@ impl LuaReflectReference {
117122
e,
118123
))
119124
})
120-
// r.set(other).map_err(|e| {
121-
// ScriptError::new_runtime_error(format!(
122-
// "Invalid assignment `{:?}` = `{:?}`. Wrong type.",
123-
// self.0.clone(),
124-
// e,
125-
// ))
126-
// })
127125
})?;
128126
Ok(())
129127
} else {
@@ -223,6 +221,10 @@ impl TealData for LuaReflectReference {
223221
self_.set_with_lua_proxy(l, value)
224222
},
225223
);
224+
225+
m.add_meta_function(MetaMethod::Len, |l, self_: LuaReflectReference| {
226+
self_.len(l)
227+
})
226228
}
227229
}
228230

crates/languages/bevy_mod_scripting_lua/src/bindings/world.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,19 @@ impl TealData for LuaWorld {
183183

184184
methods.add_method(
185185
"get_resource",
186-
|_, this, resource_id: LuaReflectValProxy<ComponentId>| {
186+
|_, this, registration: LuaValProxy<ScriptTypeRegistration>| {
187187
let world = this.0.read().ok_or_else(|| {
188188
mlua::Error::external(ScriptError::new_reflection_error("Stale world access"))
189189
})?;
190-
let out: Result<LuaValProxy<ReflectReference>, ErrorProxy<ScriptError>> = world
191-
.proxy_call(resource_id, |resource_id| world.get_resource(resource_id))
192-
.map_err(mlua::Error::external)?;
190+
let out: Result<Option<LuaValProxy<ReflectReference>>, ErrorProxy<ScriptError>> =
191+
world
192+
.proxy_call(registration, |registration| {
193+
match registration.resource_id {
194+
Some(resource_id) => world.get_resource(resource_id),
195+
None => Ok(None),
196+
}
197+
})
198+
.map_err(mlua::Error::external)?;
193199

194200
Ok(TypenameProxy::<_, LuaReflectRefProxy<ReflectReference>>::new(out))
195201
},
@@ -213,12 +219,17 @@ impl TealData for LuaWorld {
213219

214220
methods.add_method(
215221
"has_resource",
216-
|_, this, resource_id: LuaReflectValProxy<ComponentId>| {
222+
|_, this, registration: LuaValProxy<ScriptTypeRegistration>| {
217223
let world = this.0.read().ok_or_else(|| {
218224
mlua::Error::external(ScriptError::new_reflection_error("Stale world access"))
219225
})?;
220226
let out: bool = world
221-
.proxy_call(resource_id, |resource_id| world.has_resource(resource_id))
227+
.proxy_call(registration, |registration| {
228+
match registration.resource_id {
229+
Some(resource_id) => world.has_resource(resource_id),
230+
None => false,
231+
}
232+
})
222233
.map_err(mlua::Error::external)?;
223234

224235
Ok(out)
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
function Test()
2-
local entity = world:spawn()
3-
local type = world:get_type_by_name('TestComponent')
1+
local entity = world:spawn()
2+
local type = world:get_type_by_name('TestComponent')
3+
4+
assert_throws(function()
45
world:add_default_component(entity, type)
5-
end
66

7-
local success,err = pcall(Test)
8-
assert(not success, 'No error thrown')
9-
assert(string.find(tostring(err), 'Does not have ReflectDefault or ReflectFromWorld'), 'Error contains wrong message: ' .. tostring(err))
7+
end, "Does not have ReflectDefault or ReflectFromWorld data registered")
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
function Test()
2-
local entity = world:spawn()
3-
local _type = world:get_type_by_name('CompWithDefault')
1+
local entity = world:spawn()
2+
local _type = world:get_type_by_name('CompWithDefault')
43

4+
assert_throws(function()
55
world:add_default_component(entity, _type)
6-
end
7-
8-
local success,err = pcall(Test)
9-
assert(not success, 'No error thrown')
10-
assert(string.find(tostring(err), 'Does not have ReflectComponent'), 'Error contains wrong message: ' .. tostring(err))
6+
end, "Does not have ReflectComponent")
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
function Test()
2-
local entity = world:spawn()
3-
local _type = world:get_type_by_name('CompWithFromWorld')
1+
local entity = world:spawn()
2+
local _type = world:get_type_by_name('CompWithFromWorld')
43

4+
assert_throws(function()
55
world:add_default_component(entity, _type)
6-
end
7-
8-
local success,err = pcall(Test)
9-
assert(not success, 'No error thrown')
10-
assert(string.find(tostring(err), 'Does not have ReflectComponent'), 'Error contains wrong message: ' .. tostring(err))
6+
end, 'Does not have ReflectComponent data registered')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
local component = world:get_type_by_name("TestComponent")
2+
local entity = world:spawn()
3+
local retrieved = world:get_component(entity, component)
4+
5+
assert(retrieved == nil, "Component found")

0 commit comments

Comments
 (0)