Implement mechanism for implementing roblox methods only on certain classes

This commit is contained in:
Filip Tibell 2023-03-22 11:20:47 +01:00
parent 9f13b8e667
commit b0d401421e
No known key found for this signature in database
4 changed files with 82 additions and 2 deletions

View file

@ -0,0 +1,20 @@
use mlua::prelude::*;
use crate::shared::classes::add_class_restricted_method;
use super::Instance;
pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(methods: &mut M) {
add_class_restricted_method(
methods,
"DataModel",
"GetService",
|_, _, _service_name: String| Ok(()),
);
add_class_restricted_method(
methods,
"DataModel",
"FindService",
|_, _, _service_name: String| Ok(()),
);
}

View file

@ -15,6 +15,8 @@ use crate::{
shared::instance::{class_exists, class_is_a, find_property_info},
};
mod data_model;
lazy_static::lazy_static! {
static ref INTERNAL_DOM: RwLock<WeakDom> =
RwLock::new(WeakDom::new(DomInstanceBuilder::new("ROOT")));
@ -865,8 +867,9 @@ impl LuaUserData for Instance {
.find_ancestor(|ancestor| ancestor.referent() == instance.dom_ref)
.is_some())
});
// FUTURE: We could pass the "methods" struct to some other functions
// here to add inheritance-like behavior and class-specific methods
// Here we add inheritance-like behavior for instances by creating
// methods that are restricted to specific classnames / base classes
data_model::add_methods(methods);
}
}

View file

@ -0,0 +1,56 @@
use mlua::prelude::*;
use crate::instance::Instance;
use super::instance::class_is_a;
pub(crate) fn add_class_restricted_method<'lua, M: LuaUserDataMethods<'lua, Instance>, A, R, F>(
methods: &mut M,
class_name: &'static str,
method_name: &'static str,
method: F,
) where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Fn(&'lua Lua, &Instance, A) -> LuaResult<R>,
{
methods.add_method(method_name, move |lua, this, args| {
if class_is_a(this.get_class_name(), class_name).unwrap_or(false) {
method(lua, this, args)
} else {
Err(LuaError::RuntimeError(format!(
"{} is not a valid member of {}",
method_name, class_name
)))
}
});
}
#[allow(dead_code)]
pub(crate) fn add_class_restricted_method_mut<
'lua,
M: LuaUserDataMethods<'lua, Instance>,
A,
R,
F,
>(
methods: &mut M,
class_name: &'static str,
method_name: &'static str,
method: F,
) where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Fn(&'lua Lua, &mut Instance, A) -> LuaResult<R>,
{
methods.add_method_mut(method_name, move |lua, this, args| {
if class_is_a(this.get_class_name(), class_name).unwrap_or(false) {
method(lua, this, args)
} else {
Err(LuaError::RuntimeError(format!(
"{} is not a valid member of {}",
method_name, class_name
)))
}
});
}

View file

@ -1,2 +1,3 @@
pub(crate) mod classes;
pub(crate) mod instance;
pub(crate) mod userdata;