diff --git a/lib/roblox_emulator/src/runner/brickcolor.rs b/lib/roblox_emulator/src/runner/brickcolor.rs index b864684..00276df 100644 --- a/lib/roblox_emulator/src/runner/brickcolor.rs +++ b/lib/roblox_emulator/src/runner/brickcolor.rs @@ -9,15 +9,15 @@ impl BrickColor{ } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let brickcolor_table=lua.create_table()?; + let table=lua.create_table()?; - brickcolor_table.raw_set("new", + table.raw_set("new", lua.create_function(|_,name:mlua::String| Ok(BrickColor::from_name(&*name.to_str()?)) )? )?; - globals.set("BrickColor",brickcolor_table)?; + globals.set("BrickColor",table)?; Ok(()) } diff --git a/lib/roblox_emulator/src/runner/cframe.rs b/lib/roblox_emulator/src/runner/cframe.rs index 10aabac..fa60622 100644 --- a/lib/roblox_emulator/src/runner/cframe.rs +++ b/lib/roblox_emulator/src/runner/cframe.rs @@ -1,4 +1,6 @@ -use super::util::coerce_float32; +use mlua::FromLua; + +use super::number::Number; use super::vector3::Vector3; #[derive(Clone,Copy)] @@ -61,15 +63,15 @@ impl From<rbx_types::CFrame> for CFrame{ } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let cframe_table=lua.create_table()?; + let table=lua.create_table()?; //CFrame.new - cframe_table.raw_set("new", - lua.create_function(|_,tuple:( - mlua::Value,mlua::Value,Option<f32>, - Option<f32>,Option<f32>,Option<f32>, - Option<f32>,Option<f32>,Option<f32>, - Option<f32>,Option<f32>,Option<f32>, + table.raw_set("new", + lua.create_function(|lua,tuple:( + mlua::Value,mlua::Value,Option<Number>, + Option<Number>,Option<Number>,Option<Number>, + Option<Number>,Option<Number>,Option<Number>, + Option<Number>,Option<Number>,Option<Number>, )|match tuple{ //CFrame.new(pos) ( @@ -98,30 +100,30 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ None,None,None, None,None,None, None,None,None, - )=>Ok(CFrame::point(coerce_float32(&x)?,coerce_float32(&y)?,z)), + )=>Ok(CFrame::point(Number::from_lua(x,lua)?.into(),Number::from_lua(y,lua)?.into(),z.into())), //CFrame.new(x,y,z,xx,yx,zx,xy,yy,zy,xz,yz,zz) ( - mlua::Value::Number(x),mlua::Value::Number(y),Some(z), + x,y,Some(z), Some(xx),Some(yx),Some(zx), Some(xy),Some(yy),Some(zy), Some(xz),Some(yz),Some(zz), - )=>Ok(CFrame::new(x as f32,y as f32,z, - xx,yx,zx, - xy,yy,zy, - xz,yz,zz, + )=>Ok(CFrame::new(Number::from_lua(x,lua)?.into(),Number::from_lua(y,lua)?.into(),z.into(), + xx.into(),yx.into(),zx.into(), + xy.into(),yy.into(),zy.into(), + xz.into(),yz.into(),zz.into(), )), _=>Err(mlua::Error::runtime("Invalid arguments")) })? )?; //CFrame.Angles - cframe_table.raw_set("Angles", - lua.create_function(|_,(x,y,z):(f32,f32,f32)| - Ok(CFrame::angles(x,y,z)) + table.raw_set("Angles", + lua.create_function(|_,(x,y,z):(Number,Number,Number)| + Ok(CFrame::angles(x.into(),y.into(),z.into())) )? )?; - globals.set("CFrame",cframe_table)?; + globals.set("CFrame",table)?; Ok(()) } diff --git a/lib/roblox_emulator/src/runner/color3.rs b/lib/roblox_emulator/src/runner/color3.rs index a41aba0..2f1d1e0 100644 --- a/lib/roblox_emulator/src/runner/color3.rs +++ b/lib/roblox_emulator/src/runner/color3.rs @@ -1,3 +1,5 @@ +use super::number::Number; + #[derive(Clone,Copy)] pub struct Color3{ r:f32, @@ -24,20 +26,20 @@ impl From<Color3> for rbx_types::Color3{ } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let color3_table=lua.create_table()?; + let table=lua.create_table()?; - color3_table.raw_set("new", - lua.create_function(|_,(r,g,b):(f32,f32,f32)| - Ok(Color3::new(r,g,b)) + table.raw_set("new", + lua.create_function(|_,(r,g,b):(Number,Number,Number)| + Ok(Color3::new(r.into(),g.into(),b.into())) )? )?; - color3_table.raw_set("fromRGB", + table.raw_set("fromRGB", lua.create_function(|_,(r,g,b):(u8,u8,u8)| Ok(Color3::from_rgb(r,g,b)) )? )?; - globals.set("Color3",color3_table)?; + globals.set("Color3",table)?; Ok(()) } diff --git a/lib/roblox_emulator/src/runner/color_sequence.rs b/lib/roblox_emulator/src/runner/color_sequence.rs index 819fa2e..e5b100c 100644 --- a/lib/roblox_emulator/src/runner/color_sequence.rs +++ b/lib/roblox_emulator/src/runner/color_sequence.rs @@ -1,31 +1,30 @@ -#[derive(Clone,Copy)] -pub struct ColorSequence{} +#[derive(Clone)] +pub struct ColorSequence(rbx_types::ColorSequence); impl ColorSequence{ - pub const fn new()->Self{ - Self{} + pub const fn new(keypoints:Vec<rbx_types::ColorSequenceKeypoint>)->Self{ + Self(rbx_types::ColorSequence{keypoints}) } } -impl Into<rbx_types::ColorSequence> for ColorSequence{ - fn into(self)->rbx_types::ColorSequence{ - rbx_types::ColorSequence{ - keypoints:Vec::new() - } +impl From<ColorSequence> for rbx_types::ColorSequence{ + fn from(value:ColorSequence)->rbx_types::ColorSequence{ + let ColorSequence(sequence)=value; + sequence } } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let number_sequence_table=lua.create_table()?; + let table=lua.create_table()?; - number_sequence_table.raw_set("new", + table.raw_set("new", lua.create_function(|_,_:mlua::MultiValue| - Ok(ColorSequence::new()) + Ok(ColorSequence::new(Vec::new())) )? )?; - globals.set("ColorSequence",number_sequence_table)?; + globals.set("ColorSequence",table)?; Ok(()) } impl mlua::UserData for ColorSequence{} -type_from_lua_userdata!(ColorSequence); +type_from_lua_userdata_clone!(ColorSequence); diff --git a/lib/roblox_emulator/src/runner/instance/instance.rs b/lib/roblox_emulator/src/runner/instance/instance.rs index dc084d2..a475de7 100644 --- a/lib/roblox_emulator/src/runner/instance/instance.rs +++ b/lib/roblox_emulator/src/runner/instance/instance.rs @@ -5,7 +5,7 @@ use rbx_types::Ref; use rbx_dom_weak::{Ustr,InstanceBuilder,WeakDom}; use crate::runner::vector3::Vector3; -use crate::runner::util::coerce_float32; +use crate::runner::number::Number; // disallow non-static lifetimes fn static_ustr(s:&'static str)->rbx_dom_weak::Ustr{ @@ -17,10 +17,10 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ lua.set_app_data(ClassMethodsStore::default()); lua.set_app_data(InstanceValueStore::default()); - let instance_table=lua.create_table()?; + let table=lua.create_table()?; //Instance.new - instance_table.raw_set("new", + table.raw_set("new", lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{ let class_name_str=&*class_name.to_str()?; let parent=parent.unwrap_or(Instance::nil()); @@ -30,7 +30,7 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ })? )?; - globals.set("Instance",instance_table)?; + globals.set("Instance",table)?; Ok(()) } @@ -360,7 +360,7 @@ impl mlua::UserData for Instance{ rbx_types::Variant::Vector3(typed_value.into()) }, rbx_reflection::DataType::Value(rbx_types::VariantType::Float32)=>{ - let typed_value:f32=coerce_float32(&value)?; + let typed_value=Number::from_lua(value.clone(),lua)?.to_f32(); rbx_types::Variant::Float32(typed_value) }, rbx_reflection::DataType::Enum(enum_name)=>{ @@ -368,7 +368,7 @@ impl mlua::UserData for Instance{ &mlua::Value::Integer(int)=>Ok(rbx_types::Enum::from_u32(int as u32)), &mlua::Value::Number(num)=>Ok(rbx_types::Enum::from_u32(num as u32)), mlua::Value::String(s)=>{ - let e=db.enums.get(enum_name).ok_or_else(||mlua::Error::runtime("Database DataType Enum name does not exist"))?; + let e=db.enums.get(enum_name).ok_or_else(||mlua::Error::runtime("Database DataType Enum name does not exist"))?; Ok(rbx_types::Enum::from_u32(*e.items.get(&*s.to_str()?).ok_or_else(||mlua::Error::runtime("Invalid enum item"))?)) }, mlua::Value::UserData(any_user_data)=>{ @@ -404,8 +404,8 @@ impl mlua::UserData for Instance{ rbx_types::Variant::NumberSequence(typed_value.clone().into()) }, rbx_reflection::DataType::Value(rbx_types::VariantType::ColorSequence)=>{ - let typed_value:crate::runner::color_sequence::ColorSequence=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected ColorSequence"))?.borrow()?; - rbx_types::Variant::ColorSequence(typed_value.into()) + let typed_value:&crate::runner::color_sequence::ColorSequence=&*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected ColorSequence"))?.borrow()?; + rbx_types::Variant::ColorSequence(typed_value.clone().into()) }, rbx_reflection::DataType::Value(rbx_types::VariantType::ContentId)=>{ let typed_value=value.as_str().ok_or_else(||mlua::Error::runtime("Expected string"))?.to_owned(); diff --git a/lib/roblox_emulator/src/runner/macros.rs b/lib/roblox_emulator/src/runner/macros.rs index 6e097ad..c85e097 100644 --- a/lib/roblox_emulator/src/runner/macros.rs +++ b/lib/roblox_emulator/src/runner/macros.rs @@ -10,6 +10,18 @@ macro_rules! type_from_lua_userdata{ } }; } +macro_rules! type_from_lua_userdata_clone{ + ($ty:ident)=>{ + impl mlua::FromLua for $ty{ + fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result<Self,mlua::Error>{ + match value{ + mlua::Value::UserData(ud)=>Ok(ud.borrow::<Self>()?.clone()), + other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!($ty),other))), + } + } + } + }; +} macro_rules! type_from_lua_userdata_lua_lifetime{ ($ty:ident)=>{ impl mlua::FromLua for $ty<'static>{ diff --git a/lib/roblox_emulator/src/runner/mod.rs b/lib/roblox_emulator/src/runner/mod.rs index ea8f690..6f71f7e 100644 --- a/lib/roblox_emulator/src/runner/mod.rs +++ b/lib/roblox_emulator/src/runner/mod.rs @@ -1,13 +1,13 @@ #[macro_use] mod macros; mod runner; -mod util; mod r#enum; mod udim; mod udim2; mod color3; mod cframe; +mod number; mod vector3; mod brickcolor; pub mod instance; diff --git a/lib/roblox_emulator/src/runner/number.rs b/lib/roblox_emulator/src/runner/number.rs new file mode 100644 index 0000000..7471c27 --- /dev/null +++ b/lib/roblox_emulator/src/runner/number.rs @@ -0,0 +1,43 @@ +// the goal of this module is to provide an intermediate type +// that is guaranteed to be some kind of number, and provide +// methods to coerce it into various more specific types. + +#[derive(Clone,Copy)] +pub enum Number{ + Integer(i32), + Number(f64), +} +macro_rules! impl_ty{ + ($ident:ident,$ty:ty)=>{ + impl Number{ + #[inline] + pub fn $ident(self)->$ty{ + match self{ + Self::Integer(int)=>int as $ty, + Self::Number(num)=>num as $ty, + } + } + } + impl From<Number> for $ty{ + fn from(value:Number)->$ty{ + value.$ident() + } + } + }; +} +impl_ty!(to_u32,u32); +impl_ty!(to_i32,i32); +impl_ty!(to_f32,f32); +impl_ty!(to_u64,u64); +impl_ty!(to_i64,i64); +impl_ty!(to_f64,f64); + +impl mlua::FromLua for Number{ + fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result<Self,mlua::Error>{ + match value{ + mlua::Value::Integer(int)=>Ok(Number::Integer(int)), + mlua::Value::Number(num)=>Ok(Number::Number(num)), + other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!(Number),other))), + } + } +} diff --git a/lib/roblox_emulator/src/runner/number_range.rs b/lib/roblox_emulator/src/runner/number_range.rs index c46a8ec..d7dcb79 100644 --- a/lib/roblox_emulator/src/runner/number_range.rs +++ b/lib/roblox_emulator/src/runner/number_range.rs @@ -1,4 +1,4 @@ -use super::util::coerce_float32; +use super::number::Number; #[derive(Clone)] pub struct NumberRange(rbx_types::NumberRange); @@ -18,14 +18,11 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ let table=lua.create_table()?; table.raw_set("new", - lua.create_function(|_,(min,max):(mlua::Value,mlua::Value)|{ - let min=coerce_float32(&min)?; - if max.is_nil(){ - Ok(NumberRange::new(min,min)) - }else{ - let max=coerce_float32(&max)?; - Ok(NumberRange::new(min,max)) - } + lua.create_function(|_,(min,max):(Number,Option<Number>)|{ + Ok(match max{ + Some(max)=>NumberRange::new(min.into(),max.into()), + None=>NumberRange::new(min.into(),min.into()), + }) })? )?; @@ -35,11 +32,4 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ } impl mlua::UserData for NumberRange{} -impl mlua::FromLua for NumberRange{ - fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result<Self,mlua::Error>{ - match value{ - mlua::Value::UserData(ud)=>Ok(ud.borrow::<Self>()?.clone()), - other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!(NumberRange),other))), - } - } -} +type_from_lua_userdata_clone!(NumberRange); diff --git a/lib/roblox_emulator/src/runner/number_sequence.rs b/lib/roblox_emulator/src/runner/number_sequence.rs index deebb05..f1e910c 100644 --- a/lib/roblox_emulator/src/runner/number_sequence.rs +++ b/lib/roblox_emulator/src/runner/number_sequence.rs @@ -13,15 +13,15 @@ impl From<NumberSequence> for rbx_types::NumberSequence{ } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let number_sequence_table=lua.create_table()?; + let table=lua.create_table()?; - number_sequence_table.raw_set("new", + table.raw_set("new", lua.create_function(|_,_:mlua::MultiValue| Ok(NumberSequence::new(Vec::new())) )? )?; - globals.set("NumberSequence",number_sequence_table)?; + globals.set("NumberSequence",table)?; Ok(()) } diff --git a/lib/roblox_emulator/src/runner/udim.rs b/lib/roblox_emulator/src/runner/udim.rs index 25ae58f..87eda7e 100644 --- a/lib/roblox_emulator/src/runner/udim.rs +++ b/lib/roblox_emulator/src/runner/udim.rs @@ -1,3 +1,5 @@ +use super::number::Number; + #[derive(Clone,Copy)] pub struct UDim(rbx_types::UDim); impl UDim{ @@ -15,8 +17,8 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ let table=lua.create_table()?; table.raw_set("new", - lua.create_function(|_,(scale,offset):(f32,i32)| - Ok(UDim::new(scale,offset)) + lua.create_function(|_,(scale,offset):(Number,i32)| + Ok(UDim::new(scale.into(),offset)) )? )?; diff --git a/lib/roblox_emulator/src/runner/udim2.rs b/lib/roblox_emulator/src/runner/udim2.rs index c45cd7a..d0406ae 100644 --- a/lib/roblox_emulator/src/runner/udim2.rs +++ b/lib/roblox_emulator/src/runner/udim2.rs @@ -1,4 +1,5 @@ use super::udim::UDim; +use super::number::Number; #[derive(Clone,Copy)] pub struct UDim2(rbx_types::UDim2); @@ -15,8 +16,8 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ let table=lua.create_table()?; table.raw_set("new", - lua.create_function(|_,(sx,ox,sy,oy):(f32,i32,f32,i32)| - Ok(UDim2::new(sx,ox,sy,oy)) + lua.create_function(|_,(sx,ox,sy,oy):(Number,i32,Number,i32)| + Ok(UDim2::new(sx.into(),ox,sy.into(),oy)) )? )?; diff --git a/lib/roblox_emulator/src/runner/util.rs b/lib/roblox_emulator/src/runner/util.rs deleted file mode 100644 index 6e92474..0000000 --- a/lib/roblox_emulator/src/runner/util.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub fn coerce_float32(value:&mlua::Value)->mlua::Result<f32>{ - match value{ - &mlua::Value::Integer(i)=>Ok(i as f32), - &mlua::Value::Number(f)=>Ok(f as f32), - _=>Err(mlua::Error::runtime("Expected f32")), - } -} diff --git a/lib/roblox_emulator/src/runner/vector3.rs b/lib/roblox_emulator/src/runner/vector3.rs index 7baa91e..3bcb877 100644 --- a/lib/roblox_emulator/src/runner/vector3.rs +++ b/lib/roblox_emulator/src/runner/vector3.rs @@ -1,3 +1,5 @@ +use super::number::Number; + #[derive(Clone,Copy)] pub struct Vector3(pub(crate)glam::Vec3A); @@ -8,23 +10,24 @@ impl Vector3{ } pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ - let vector3_table=lua.create_table()?; + let table=lua.create_table()?; //Vector3.new - vector3_table.raw_set("new", - lua.create_function(|_,(x,y,z):(f32,f32,f32)| - Ok(Vector3::new(x,y,z)) + table.raw_set("new", + lua.create_function(|_,(x,y,z):(Number,Number,Number)| + Ok(Vector3::new(x.into(),y.into(),z.into())) )? )?; - globals.set("Vector3",vector3_table)?; + globals.set("Vector3",table)?; Ok(()) } impl Into<rbx_types::Vector3> for Vector3{ fn into(self)->rbx_types::Vector3{ - rbx_types::Vector3::new(self.0.x,self.0.y,self.0.z) + let Vector3(v)=self; + rbx_types::Vector3::new(v.x,v.y,v.z) } }