Compare commits

...

2 Commits

Author SHA1 Message Date
SeanOMik ef2b0bf326
ecs,scripting: fix invalid resources being passed to lua
CI / build (pull_request) Failing after 3m35s Details
The issue was World::get_resource_ptr, it was returning a pointer to the AtomicRefCell instead of the actual resource data
2024-09-29 14:35:24 -04:00
SeanOMik fa22a0310c
scripting: switch to latest mlua, create custom impl of lua's `getmetatable` 2024-09-29 15:59:48 -04:00
15 changed files with 141 additions and 124 deletions

10
Cargo.lock generated
View File

@ -2062,22 +2062,20 @@ dependencies = [
[[package]]
name = "mlua"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
version = "0.10.0-beta.2"
source = "git+https://github.com/mlua-rs/mlua?rev=4dddf3c18d4590f7c92214fa592c3faca3d2c812#4dddf3c18d4590f7c92214fa592c3faca3d2c812"
dependencies = [
"bstr",
"mlua-sys",
"num-traits",
"once_cell",
"parking_lot",
"rustc-hash 2.0.0",
]
[[package]]
name = "mlua-sys"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebe026d6bd1583a9cf9080e189030ddaea7e6f5f0deb366a8e26f8a26c4135b8"
source = "git+https://github.com/mlua-rs/mlua?rev=4dddf3c18d4590f7c92214fa592c3faca3d2c812#4dddf3c18d4590f7c92214fa592c3faca3d2c812"
dependencies = [
"cc",
"cfg-if",

View File

@ -1,10 +1,13 @@
---Return the userdata's name from its metatable
---Return the userdata's name from its metatable.
---
---Returns nil if the userdata doesn't have a metatable.
---@param val userdata
---@return string
---@return string|nil
function udname(val)
local tbl = getmetatable(val)
if type(tbl) == "boolean" then
error("what, got a boolean??: " .. tostring(tbl), 1)
local tbl = debug.getmetatable(val)
if tbl == nil then
return nil
end
return tbl.__name
@ -15,14 +18,14 @@ function on_init()
local cube = world:request_res("../assets/cube-texture-embedded.gltf")
print("Loaded textured cube (" .. udname(cube) .. ")")
--[[ cube:wait_until_loaded()
cube:wait_until_loaded()
local scenes = cube:scenes()
local cube_scene = scenes[1]
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
local e = world:spawn(pos, cube_scene)
print("spawned entity " .. tostring(e)) ]]
print("spawned entity " .. tostring(e))
end
--[[ function on_first()
@ -48,12 +51,12 @@ function on_update()
end, Transform) ]]
---@type number
--[[ local dt = world:resource(DeltaTime)
local dt = world:resource(DeltaTime)
world:view(function (t)
t:translate(0, 0.15 * dt, 0)
return t
end, Transform) ]]
end, Transform)
end
--[[ function on_post_update()

View File

@ -509,7 +509,11 @@ impl World {
/// Attempts to find a resource in the world and returns a NonNull pointer to it
pub unsafe fn get_resource_ptr<T: ResourceObject>(&self) -> Option<NonNull<T>> {
self.resources.get(&TypeId::of::<T>())
.map(|d| unsafe { NonNull::new_unchecked(d.data.as_ptr() as *mut T) })
.map(|d| unsafe {
let data = d.data.borrow();
let ptr = NonNull::from(&data.res);
NonNull::new_unchecked(ptr.as_ptr() as *mut T)
})
}
pub fn archetype_count(&self) -> usize {

View File

@ -22,7 +22,9 @@ tracing = "0.1.37"
atomic_refcell = "0.1.13"
# enabled with lua feature
mlua = { version = "0.9.9", features = ["lua54", "send"], optional = true } # luajit maybe?
#
#mlua = { version = "0.9.9", features = ["lua54", "send"], optional = true } # luajit maybe?
mlua = { git = "https://github.com/mlua-rs/mlua", rev = "4dddf3c18d4590f7c92214fa592c3faca3d2c812", features = ["lua54", "send"], optional = true } # luajit maybe?
#elua = { path = "./elua", optional = true }
itertools = "0.12.0"
paste = "1.0.14"

View File

@ -187,7 +187,7 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
}
impl mlua::UserData for #wrapper_name {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("path", |_, this| Ok(this.path()));
fields.add_field_method_get("version", |_, this| Ok(this.version()));
fields.add_field_method_get("uuid", |_, this| Ok(this.uuid().to_string()));
@ -204,7 +204,7 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
#(#custom_getters)*
}
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("is_watched", |_, this, ()| {
Ok(this.is_watched())
});
@ -234,8 +234,8 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro
}
}
impl<'a> mlua::FromLua<'a> for #wrapper_name {
fn from_lua(val: mlua::Value<'a>, _: &'a mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for #wrapper_name {
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
let tyname = val.type_name();
let ud = val.as_userdata()
.ok_or(mlua::Error::external(crate::lua::Error::type_mismatch(#ud_name, &tyname)))?;

View File

@ -224,7 +224,7 @@ impl MetaMethod {
// this is the body of the else statement
{
// try to get the name of the userdata for the error message
if let Ok(mt) = ud.get_metatable() {
if let Ok(mt) = ud.metatable() {
if let Ok(name) = mt.get::<String>("__name") {
return Err(mlua::Error::BadArgument {
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
@ -480,8 +480,8 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
}
}
impl<'lua> mlua::FromLua<'lua> for #wrapper_typename {
fn from_lua(value: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for #wrapper_typename {
fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
match value {
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
_ => panic!("Attempt to get {} from a {} value", stringify!(#wrapper_typename), value.type_name()),
@ -490,11 +490,11 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token
}
impl mlua::UserData for #wrapper_typename {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
#(#field_get_set_pairs)*
}
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
#lua_reflects
#new_func_tokens

View File

@ -6,38 +6,36 @@ use lyra_reflect::TypeRegistry;
#[cfg(feature = "lua")]
use super::ReflectLuaProxy;
use crate::ScriptWorldPtr;
#[cfg(feature = "lua")]
pub struct ReflectedItem<'a> {
pub struct ReflectedItem {
//pub proxy: &'a ReflectLuaProxy,
pub comp_ptr: NonNull<u8>,
pub comp_val: mlua::Value<'a>,
pub comp_val: mlua::Value,
}
#[cfg(feature = "lua")]
pub struct ReflectedRow<'a> {
pub struct ReflectedRow {
pub entity: Entity,
pub row: Vec<ReflectedItem<'a>>,
pub row: Vec<ReflectedItem>,
}
pub struct ReflectedIterator {
pub world: ScriptWorldPtr,
pub struct ReflectedIterator<'a> {
pub world: &'a lyra_ecs::World,
pub dyn_view: DynamicViewStateIter,
pub reflected_components: Option<NonNull<TypeRegistry>>
}
impl ReflectedIterator {
impl<'a> ReflectedIterator<'a> {
#[cfg(feature = "lua")]
pub fn next_lua<'a>(&mut self, lua: &'a mlua::Lua) -> Option<ReflectedRow<'a>> {
pub fn next_lua(&mut self, lua: &mlua::Lua) -> Option<ReflectedRow> {
use mlua::IntoLua;
let world = self.world.read();
let n = self.dyn_view.next(&world);
//let world = self.world.read();
let n = self.dyn_view.next(&self.world);
if let Some((en, row)) = n {
if self.reflected_components.is_none() {
self.reflected_components = world.get_resource::<TypeRegistry>()
self.reflected_components = self.world.get_resource::<TypeRegistry>()
.map(|r| NonNull::from(r.deref()));
}

View File

@ -2,7 +2,7 @@ pub mod dynamic_iter;
pub use dynamic_iter::*;
pub mod world;
use mlua::AnyUserDataExt;
use mlua::ObjectLike;
pub use world::*;
pub mod script;
@ -113,24 +113,24 @@ pub trait RegisterLuaType {
/// Register a type to Lua that **is not wrapped**.
fn register_lua_type<'a, T>(&mut self)
where
T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData;
T: Reflect + LuaProxy + Clone + mlua::FromLua + mlua::UserData;
/// Registers a type to Lua that is wrapped another type.
/// This would be used for something like `UserdataRef<T>`.
fn register_lua_wrapper<'a, W>(&mut self)
where
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData;
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua + mlua::UserData;
/// Registers a type to Lua that can be converted into and from Lua types.
fn register_lua_convert<T>(&mut self)
where
T: Clone + for<'a> mlua::FromLua<'a> + for<'a> mlua::IntoLua<'a> + LuaWrapper + 'static;
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static;
}
impl RegisterLuaType for World {
fn register_lua_type<'a, T>(&mut self)
where
T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData
T: Reflect + LuaProxy + Clone + mlua::FromLua + mlua::UserData
{
let mut registry = self.get_resource_mut::<TypeRegistry>().unwrap();
@ -142,7 +142,7 @@ impl RegisterLuaType for World {
fn register_lua_wrapper<'a, W>(&mut self)
where
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData
W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua + mlua::UserData
{
let mut registry = self.get_resource_mut::<TypeRegistry>().unwrap();
@ -152,7 +152,7 @@ impl RegisterLuaType for World {
fn register_lua_convert<T>(&mut self)
where
T: Clone + for<'a> mlua::FromLua<'a> + for<'a> mlua::IntoLua<'a> + LuaWrapper + 'static,
T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static,
{
let mut registry = self.get_resource_mut::<TypeRegistry>().unwrap();
@ -161,8 +161,8 @@ impl RegisterLuaType for World {
}
}
impl<'lua> mlua::FromLua<'lua> for ScriptBorrow {
fn from_lua(value: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for ScriptBorrow {
fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
match value {
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
_ => unreachable!(),
@ -176,6 +176,6 @@ impl mlua::UserData for ScriptBorrow {
/// Helper function used for reflecting userdata as a ScriptBorrow
pub fn reflect_user_data(ud: &mlua::AnyUserData) -> ScriptBorrow {
ud.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
ud.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
.expect("Type does not implement internal reflect method properly")
}

View File

@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex};
use std::{ops::Deref, sync::{Arc, Mutex}};
use mlua::AnyUserDataExt;
use mlua::{AnyUserData, ObjectLike};
use tracing::{debug, debug_span};
use crate::{ScriptApiProvider, ScriptData};
@ -58,9 +58,9 @@ impl ScriptApiProvider for UtilityApiProvider {
},
mlua::Value::UserData(ud) => {
if let Ok(tos) =
ud.get::<_, mlua::Function>(mlua::MetaMethod::ToString.name())
ud.get::<mlua::Function>(mlua::MetaMethod::ToString.name())
{
tos.call::<_, String>(())?
tos.call::<String>(())?
} else {
return Err(mlua::Error::runtime(
"UserData does not implement MetaMethod '__tostring'",
@ -73,7 +73,7 @@ impl ScriptApiProvider for UtilityApiProvider {
));
},
mlua::Value::Error(error) => {
return Err(error.clone());
return Err(error.deref().clone());
},
},
None => {
@ -123,8 +123,8 @@ impl ScriptApiProvider for UtilityApiProvider {
formatted = format!("{}{}", formatted, text);
lua.globals()
.get::<_, mlua::Function>("print")?
.call::<_, ()>(formatted)?;
.get::<mlua::Function>("print")?
.call::<()>(formatted)?;
Ok(())
};
@ -141,9 +141,24 @@ impl ScriptApiProvider for UtilityApiProvider {
Ok(())
})?;
// a custom implementation of `getmetatable` is required since mlua protects __metatable,
// making it impossible to get the metatable of userdata.
let getmetatable_func = ctx.create_function(|lua, ud: AnyUserData| {
// the userdata is left on the stack from `lua_getmetatable`, so that needs to be
// included in the returns
let (_ud, table): (mlua::AnyUserData, mlua::Table) = unsafe {
lua.exec_raw(ud, |state| {
mlua::ffi::lua_getmetatable(state, -1);
})
}?;
Ok(table)
})?;
let globals = ctx.globals();
globals.set("printf", printf_func)?;
globals.set("print", print_func)?;
globals.set("getmetatable2", getmetatable_func)?;
Ok(())
}

View File

@ -1,6 +1,6 @@
use std::{any::TypeId, collections::HashMap, ptr::NonNull};
use mlua::{AnyUserDataExt, IntoLua};
use mlua::{ObjectLike, IntoLua};
use lyra_ecs::{ComponentInfo, DynamicBundle};
use lyra_reflect::Reflect;
@ -15,10 +15,10 @@ pub trait LuaWrapper {
/// A trait that used to convert something into lua, or to set something to a value from lua.
pub trait LuaProxy {
fn as_lua_value<'lua>(
lua: &'lua mlua::Lua,
fn as_lua_value(
lua: &mlua::Lua,
this: &dyn Reflect,
) -> mlua::Result<mlua::Value<'lua>>;
) -> mlua::Result<mlua::Value>;
fn apply(
lua: &mlua::Lua,
@ -29,15 +29,14 @@ pub trait LuaProxy {
impl<'a, T> LuaProxy for T
where
T: Reflect + Clone + mlua::FromLua<'a> + mlua::UserData
T: Reflect + Clone + mlua::FromLua + mlua::UserData
{
fn as_lua_value<'lua>(
lua: &'lua mlua::Lua,
fn as_lua_value(
lua: &mlua::Lua,
this: &dyn Reflect,
) -> mlua::Result<mlua::Value<'lua>> {
) -> mlua::Result<mlua::Value> {
let this = this.as_any().downcast_ref::<T>().unwrap();
lua.create_userdata(this.clone())
.and_then(|ud| ud.into_lua(lua))
this.clone().into_lua(lua)
}
fn apply(
@ -67,11 +66,11 @@ pub struct LuaTableProxyLookup {
#[derive(Clone)]
pub struct ReflectLuaProxy {
pub fn_as_lua:
for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<()>) -> mlua::Result<mlua::Value<'a>>,
for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<()>) -> mlua::Result<mlua::Value>,
pub fn_apply: for<'a> fn(
lua: &'a mlua::Lua,
this_ptr: NonNull<()>,
value: &'a mlua::Value<'a>,
value: &'a mlua::Value,
) -> mlua::Result<()>,
}
@ -96,7 +95,7 @@ impl ReflectLuaProxy {
/// Create from a type that implements FromLua and AsLua
pub fn from_as_and_from_lua<T>() -> Self
where
T: for<'a> mlua::FromLua<'a> + for<'a> mlua::IntoLua<'a> + Clone
T: mlua::FromLua + mlua::IntoLua + Clone
{
Self {
fn_as_lua: |lua, this| -> mlua::Result<mlua::Value> {
@ -115,8 +114,8 @@ impl ReflectLuaProxy {
}
}
impl<'lua> mlua::FromLua<'lua> for ScriptDynamicBundle {
fn from_lua(val: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for ScriptDynamicBundle {
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
match val {
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
mlua::Value::Nil => Err(Error::Nil.into()),
@ -126,10 +125,10 @@ impl<'lua> mlua::FromLua<'lua> for ScriptDynamicBundle {
}
impl mlua::UserData for ScriptDynamicBundle {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new())));
methods.add_method_mut("push", |_, this, comp: mlua::AnyUserData| {
let script_brw = comp.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
let script_brw = comp.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
let reflect = script_brw.reflect_branch.as_component_unchecked();
let refl_data = script_brw.data.unwrap();

View File

@ -11,8 +11,8 @@ fn try_call_lua_function(lua: &mlua::Lua, fn_name: &str) -> Result<(), ScriptErr
let globals = lua.globals();
if globals.contains_key(fn_name)? {
let lua_fn = globals.get::<_, mlua::Function>(fn_name)?;
lua_fn.call::<_, ()>(())
let lua_fn = globals.get::<mlua::Function>(fn_name)?;
lua_fn.call::<()>(())
.map_err(ScriptError::from)?;
}
@ -26,7 +26,7 @@ impl ScriptHost for LuaHost {
let mut ctx = Mutex::new({
// unsafe is required to allow the debug module
let s = unsafe { mlua::Lua::unsafe_new() };
s.load_from_std_lib(StdLib::ALL)?;
s.load_std_libs(StdLib::ALL)?;
s
});

View File

@ -7,14 +7,14 @@ use lyra_ecs::{
};
use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry};
use lyra_resource::ResourceManager;
use mlua::{AnyUserDataExt, IntoLua};
use mlua::{IntoLua, ObjectLike};
use super::{
reflect_user_data, wrappers::LuaResHandleToComponent, Error, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
};
impl<'lua> mlua::FromLua<'lua> for ScriptEntity {
fn from_lua(value: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for ScriptEntity {
fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
match value {
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
mlua::Value::Nil => Err(mlua::Error::external(Error::type_mismatch("ScriptEntity", "Nil"))),
@ -24,7 +24,7 @@ impl<'lua> mlua::FromLua<'lua> for ScriptEntity {
}
impl mlua::UserData for ScriptEntity {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, ()| {
Ok(format!("{:?}", this.0))
});
@ -37,8 +37,8 @@ pub enum WorldError {
LuaInvalidUsage(String),
}
impl<'lua> mlua::FromLua<'lua> for ScriptWorldPtr {
fn from_lua(val: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for ScriptWorldPtr {
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
match val {
mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
mlua::Value::Nil => Err(mlua::Error::external(Error::type_mismatch("ScriptWorldPtr", "Nil"))),
@ -48,7 +48,7 @@ impl<'lua> mlua::FromLua<'lua> for ScriptWorldPtr {
}
impl mlua::UserData for ScriptWorldPtr {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method_mut("spawn", |_, this, vals: mlua::MultiValue| {
let mut world = this.write();
@ -64,7 +64,7 @@ impl mlua::UserData for ScriptWorldPtr {
})?;
let comp_borrow = {
if let Ok(as_comp) = ud.get::<_, mlua::Function>(FN_NAME_INTERNAL_AS_COMPONENT)
if let Ok(as_comp) = ud.get::<mlua::Function>(FN_NAME_INTERNAL_AS_COMPONENT)
{
let ud = match as_comp.call(ud.clone())? {
mlua::Value::UserData(ud) => ud,
@ -72,9 +72,9 @@ impl mlua::UserData for ScriptWorldPtr {
_ => todo!(),
};
ud.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
ud.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
} else {
ud.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
ud.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
}
};
@ -139,7 +139,7 @@ impl mlua::UserData for ScriptWorldPtr {
}
mlua::Value::UserData(ud) => {
let reflect = ud
.call_function::<_, ScriptBorrow>(
.call_function::<ScriptBorrow>(
FN_NAME_INTERNAL_REFLECT_TYPE,
(),
)
@ -155,32 +155,34 @@ impl mlua::UserData for ScriptWorldPtr {
let iter = view.into_iter();
let mut reflected_iter = ReflectedIterator {
world: this.clone(),
// SAFETY: bypassing the borrow checker here to get a pointer of the world
// is required since we mutably borrow below. Its safe to do so since
// only the entity ticks are updated. They are accessing different things
// from the world.
world: unsafe { NonNull::from(&*world).as_ref() },
dyn_view: DynamicViewStateIter::from(iter),
reflected_components: None,
};
let mut current = world.current_tick();
let mut has_ticked = false;
let current = world.current_tick();
// drop read lock and acquire the write lock.
// dropping must be done to avoid mutex deadlock
drop(world);
let mut world = this.write();
while let Some(row) = reflected_iter.next_lua(lua) {
let r = row
.row
let r = row.row.into_iter()
.into_iter()
.map(|r| (r.comp_val, r.comp_ptr.cast::<()>()))
.collect::<Vec<_>>();
let (values, ptrs) =
itertools::multiunzip::<(Vec<mlua::Value>, Vec<NonNull<()>>), _>(r);
let mult_val = mlua::MultiValue::from_vec(values);
let mult_val = mlua::MultiValue::from_iter(values.into_iter());
let res: mlua::MultiValue = system.call(mult_val)?;
// if values were returned, find the type in the type registry, and apply the new values
if res.len() <= ptrs.len() {
// we only want to tick one time per system
if !has_ticked {
current = world.tick();
has_ticked = true;
}
for (comp, ptr) in res.into_iter().zip(ptrs) {
let lua_typeid = match &comp {
@ -203,7 +205,6 @@ impl mlua::UserData for ScriptWorldPtr {
};
// update the component tick
let mut world = this.write();
let arch = world.entity_archetype_mut(row.entity).unwrap();
let idx = arch.entity_indexes().get(&row.entity).unwrap().clone();
let c = arch.get_column_mut(lua_typeid).unwrap();
@ -236,20 +237,17 @@ impl mlua::UserData for ScriptWorldPtr {
methods.add_method_mut("resource", |lua, this, (ty,): (mlua::Value,)| {
let reflect = match ty {
mlua::Value::UserData(ud) => ud
.call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
.call_function::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
.expect("Type does not implement 'reflect_type' properly"),
mlua::Value::Table(t) => {
let f: mlua::Function = t.get(FN_NAME_INTERNAL_REFLECT_TYPE)?;
f.call::<_, ScriptBorrow>(())
f.call::<ScriptBorrow>(())
.expect("Type does not implement 'reflect_type' properly")
}
_ => {
panic!("how");
}
};
/* let reflect = ty
.execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ())
.expect("Type does not implement 'reflect_type' properly"); */
let mut world = this.write();
let res = reflect.reflect_branch.as_resource_unchecked();
@ -270,11 +268,11 @@ impl mlua::UserData for ScriptWorldPtr {
methods.add_method_mut("add_resource", |_, this, res: mlua::Value| {
let reflect = match res {
mlua::Value::UserData(ud) => ud
.call_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
.call_method::<ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
.expect("Type does not implement 'reflect_type' properly"),
mlua::Value::Table(t) => {
let f: mlua::Function = t.get(FN_NAME_INTERNAL_REFLECT)?;
f.call::<_, ScriptBorrow>(())
f.call::<ScriptBorrow>(())
.expect("Type does not implement 'reflect_type' properly")
}
_ => {

View File

@ -56,7 +56,7 @@ impl From<UntypedResHandle> for LuaResHandle {
}
impl mlua::UserData for LuaResHandle {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("path", |_, this| Ok(this.path()));
fields.add_field_method_get("version", |_, this| Ok(this.version()));
fields.add_field_method_get("uuid", |_, this| Ok(this.uuid().to_string()));
@ -71,7 +71,7 @@ impl mlua::UserData for LuaResHandle {
});
}
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("is_watched", |_, this, ()| {
Ok(this.is_watched())
});
@ -100,8 +100,8 @@ impl mlua::UserData for LuaResHandle {
}
}
impl<'a> mlua::FromLua<'a> for LuaResHandle {
fn from_lua(val: mlua::Value<'a>, _: &'a mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for LuaResHandle {
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
let tyname = val.type_name();
let ud = val.as_userdata()
.ok_or(mlua::Error::external(Error::type_mismatch("Handle", &tyname)))?;

View File

@ -21,14 +21,14 @@ impl std::ops::DerefMut for LuaDeltaTime {
}
}
impl<'lua> mlua::FromLua<'lua> for LuaDeltaTime {
fn from_lua(_: mlua::Value<'lua>, _: &'lua mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for LuaDeltaTime {
fn from_lua(_: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
todo!()
}
}
impl<'lua> mlua::IntoLua<'lua> for LuaDeltaTime {
fn into_lua(self, _: &'lua mlua::Lua) -> mlua::Result<mlua::Value<'lua>> {
impl mlua::IntoLua for LuaDeltaTime {
fn into_lua(self, _: &mlua::Lua) -> mlua::Result<mlua::Value> {
Ok(mlua::Value::Number(*self.0 as f64))
}
}

View File

@ -12,12 +12,12 @@ pub struct LuaActionHandler {
}
impl mlua::UserData for LuaActionHandler {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_function("new", |_, table: mlua::Table| {
let mut handler = ActionHandler::new();
// create the layouts and add them to the handler
let layouts = table.get::<_, mlua::Table>("layouts")
let layouts = table.get::<mlua::Table>("layouts")
.map_err(|_| mlua::Error::runtime("missing 'layouts' in ActionHandler table"))?;
for layout_id in layouts.sequence_values::<u32>() {
let layout_id = layout_id?;
@ -26,7 +26,7 @@ impl mlua::UserData for LuaActionHandler {
}
// add the actions to the handler
let actions = table.get::<_, mlua::Table>("actions")
let actions = table.get::<mlua::Table>("actions")
.map_err(|_| mlua::Error::runtime("missing 'actions' in ActionHandler table"))?;
for pair in actions.pairs::<String, String>() {
let (action_lbl, action_type) = pair?;
@ -42,17 +42,17 @@ impl mlua::UserData for LuaActionHandler {
}
// find the mappings and start processing them
let mappings= table.get::<_, mlua::Table>("mappings")
let mappings= table.get::<mlua::Table>("mappings")
.map_err(|_| mlua::Error::runtime("missing 'mappings' in ActionHandler table"))?;
for (map_id, tbl) in mappings.sequence_values::<mlua::Table>().enumerate() {
let tbl = tbl?;
let layout_id = tbl.get::<_, u32>("layout")?;
let layout_id = tbl.get::<u32>("layout")?;
let mut mapping = ActionMapping::new(LayoutId(layout_id), ActionMappingId(map_id as u32));
// find the binds and start processing them
// the keys are used as the action names, and then the value is an array (lua table)
let binds_tbl = tbl.get::<_, mlua::Table>("binds")
let binds_tbl = tbl.get::<mlua::Table>("binds")
.map_err(|_| mlua::Error::runtime("missing 'binds' in ActionHandler 'mappings' table"))?;
for pair in binds_tbl.pairs::<String, mlua::Table>() {
let (action_lbl, input_binds) = pair?;
@ -140,7 +140,7 @@ impl mlua::UserData for LuaActionHandler {
multi.push(name.into_lua(lua)?);
multi.push(val.into_lua(lua)?);
Ok(mlua::MultiValue::from_vec(multi))
Ok(mlua::MultiValue::from_iter(multi.into_iter()))
});
methods.add_method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
@ -153,8 +153,8 @@ impl mlua::UserData for LuaActionHandler {
}
}
impl<'a> mlua::FromLua<'a> for LuaActionHandler {
fn from_lua(val: mlua::Value<'a>, _: &'a mlua::Lua) -> mlua::Result<Self> {
impl mlua::FromLua for LuaActionHandler {
fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> {
let tyname = val.type_name();
let ud = val.as_userdata()
.ok_or(mlua::Error::external(Error::type_mismatch("ActionHandler", &tyname)))?;