diff --git a/CHANGELOG.md b/CHANGELOG.md index f42d40c..da57db4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes +* Added Instance:IsA() ([#52](https://github.com/rojo-rbx/remodel/pull/52)) ## 0.9.1 (2021-10-11) * Updated to latest rbx-dom libraries. * Increased Roblox API request timeout from 30 seconds to 3 minutes. ([#63]) diff --git a/src/roblox_api/instance.rs b/src/roblox_api/instance.rs index 855e411..a2c20b4 100644 --- a/src/roblox_api/instance.rs +++ b/src/roblox_api/instance.rs @@ -235,6 +235,40 @@ impl LuaInstance { } } + fn is_a(&self, class_name: &str) -> rlua::Result { + let tree = self.tree.lock().unwrap(); + + let instance = tree + .get_by_ref(self.id) + .ok_or_else(|| rlua::Error::external("Cannot call IsA() on a destroyed instance"))?; + + if class_name == "Instance" || instance.class == class_name { + return Ok(true); + } + + let database = rbx_reflection_database::get(); + let mut superclass_name = instance.class.as_str(); + + loop { + if class_name == superclass_name { + break Ok(true); + } + + let descriptor = database.classes.get(superclass_name).ok_or_else(|| { + rlua::Error::external(format!( + "Unable to obtain class {} from reflection database", + &superclass_name + )) + })?; + + if let Some(super_class) = &descriptor.superclass { + superclass_name = super_class; + } else { + break Ok(false); + } + } + } + fn get_class_name<'lua>( &self, context: rlua::Context<'lua>, @@ -395,6 +429,9 @@ impl UserData for LuaInstance { this.find_first_child_of_class(&class) }); + methods.add_method("IsA", |_context, this, class_name: String| { + this.is_a(&class_name) + }); methods.add_method("GetFullName", |_context, this, _args: ()| { this.get_full_name() }); diff --git a/test-scripts/is-a.lua b/test-scripts/is-a.lua new file mode 100644 index 0000000..6f37749 --- /dev/null +++ b/test-scripts/is-a.lua @@ -0,0 +1,15 @@ +local folder = Instance.new("Folder") + +assert(folder:IsA("Folder")) +assert(folder:IsA("Instance")) +assert(not folder:IsA("BasePart")) + +local spawnLocation = Instance.new("SpawnLocation") + +assert(spawnLocation:IsA("SpawnLocation")) +assert(spawnLocation:IsA("Part")) +assert(spawnLocation:IsA("FormFactorPart")) +assert(spawnLocation:IsA("BasePart")) +assert(spawnLocation:IsA("PVInstance")) +assert(spawnLocation:IsA("Instance")) +assert(not spawnLocation:IsA("Folder"))