From 3f89f2c1c5c37ad16ec7ebd33e008f8c461e3d46 Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Tue, 22 Apr 2025 21:19:24 -0700
Subject: [PATCH] roblox_emulator: implement FindFirstChildWhichIsA

---
 .../src/runner/instance/instance.rs           | 35 +++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/lib/roblox_emulator/src/runner/instance/instance.rs b/lib/roblox_emulator/src/runner/instance/instance.rs
index 5e4f60c..322ec12 100644
--- a/lib/roblox_emulator/src/runner/instance/instance.rs
+++ b/lib/roblox_emulator/src/runner/instance/instance.rs
@@ -84,6 +84,21 @@ pub fn find_first_descendant_of_class<'a>(dom:&'a rbx_dom_weak::WeakDom,instance
 	dom.descendants_of(instance.referent()).find(|&inst|inst.class==class)
 }
 
+pub fn find_first_child_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
+	let db=rbx_reflection_database::get();
+	let superclass_descriptor=db.classes.get(superclass)?;
+	instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|{
+		db.classes.get(inst.class.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
+	})
+}
+pub fn find_first_descendant_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
+	let db=rbx_reflection_database::get();
+	let superclass_descriptor=db.classes.get(superclass)?;
+	dom.descendants_of(instance.referent()).find(|inst|{
+		db.classes.get(inst.class.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
+	})
+}
+
 #[derive(Clone,Copy)]
 pub struct Instance{
 	referent:Ref,
@@ -193,10 +208,26 @@ impl mlua::UserData for Instance{
 		methods.add_method("FindFirstChildOfClass",|lua,this,(class,search_descendants):(mlua::String,Option<bool>)|{
 			let class_str=&*class.to_str()?;
 			dom_mut(lua,|dom|{
+				let inst=this.get(dom)?;
 				Ok(
 					match search_descendants.unwrap_or(false){
-						true=>find_first_descendant_of_class(dom,this.get(dom)?,class_str),
-						false=>find_first_child_of_class(dom,this.get(dom)?,class_str),
+						true=>find_first_descendant_of_class(dom,inst,class_str),
+						false=>find_first_child_of_class(dom,inst,class_str),
+					}
+					.map(|instance|
+						Instance::new_unchecked(instance.referent())
+					)
+				)
+			})
+		});
+		methods.add_method("FindFirstChildWhichIsA",|lua,this,(class,search_descendants):(mlua::String,Option<bool>)|{
+			let class_str=&*class.to_str()?;
+			dom_mut(lua,|dom|{
+				let inst=this.get(dom)?;
+				Ok(
+					match search_descendants.unwrap_or(false){
+						true=>find_first_descendant_which_is_a(dom,inst,class_str),
+						false=>find_first_child_which_is_a(dom,inst,class_str),
 					}
 					.map(|instance|
 						Instance::new_unchecked(instance.referent())