Skip to main content

rblx_godot/instance/
instance.rs

1use std::borrow::Borrow;
2use std::collections::{HashMap, HashSet};
3use std::fmt::Debug;
4use std::hash::{DefaultHasher, Hash, Hasher};
5use std::mem::swap;
6use std::ops::Deref;
7use std::ptr::NonNull;
8
9use r2g_mlua::prelude::*;
10
11use crate::core::alloc::Allocator;
12use crate::core::lua_macros::lua_getter;
13use crate::core::{get_state, get_task_scheduler_from_lua, IWeak, Irc, IrcHead, ParallelDispatch, RwLockReadGuard, RwLockWriteGuard};
14use crate::userdata::{ManagedRBXScriptSignal, RBXScriptSignal};
15
16use super::IObject;
17
18pub type DynInstance = dyn IInstance;
19pub type ManagedInstance = Irc<DynInstance>;
20pub type WeakManagedInstance = IWeak<DynInstance>;
21pub type EventsTable = HashMap<String, ManagedRBXScriptSignal>;
22
23pub trait IInstanceComponent: Sized {
24    unsafe fn weak_to_strong_instance(ptr: WeakManagedInstance) -> ManagedInstance {
25        ptr.upgrade().unwrap_unchecked()
26    }
27    fn lua_get(self: &mut RwLockReadGuard<'_, Self>, ptr: &DynInstance, lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>>;
28    fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, ptr: &DynInstance, lua: &Lua, key: &String, value: &LuaValue) -> Option<LuaResult<()>>;
29    fn clone(self: &RwLockReadGuard<'_, Self>, lua: &Lua, new_ptr: &WeakManagedInstance) -> LuaResult<Self>;
30    fn new(ptr: WeakManagedInstance, class_name: &'static str) -> Self;
31}
32
33type ReadInstanceComponent<'a> = RwLockReadGuard<'a, InstanceComponent>;
34type WriteInstanceComponent<'a> = RwLockWriteGuard<'a, InstanceComponent>;
35
36pub trait IReadInstanceComponent: Deref<Target = InstanceComponent> + Borrow<InstanceComponent> + Sized {}
37
38impl<'a> IReadInstanceComponent for ReadInstanceComponent<'a> {}
39impl<'a> IReadInstanceComponent for WriteInstanceComponent<'a> {}
40
41pub trait IInstance: IObject {
42    fn get_instance_component(&self) -> RwLockReadGuard<InstanceComponent>;
43    fn get_instance_component_mut(&self) -> RwLockWriteGuard<InstanceComponent>;
44    
45    fn lua_set(&self, lua: &Lua, name: String, val: LuaValue) -> LuaResult<()>;
46
47    fn clone_instance(&self, lua: &Lua) -> LuaResult<ManagedInstance>;
48
49    fn get_actor(&self) -> LuaResult<Option<ManagedInstance>> {
50        DynInstance::guard_find_first_ancestor_of_class(&self.get_instance_component(),"Actor".into())
51    }
52}
53
54impl DynInstance {
55    #[inline]
56    pub fn get_parent(&self) -> Option<ManagedInstance> {
57        DynInstance::guard_get_parent(&self.get_instance_component())
58    }
59    #[inline]
60    pub fn set_parent(&self, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
61        DynInstance::guard_set_parent(&mut self.get_instance_component_mut(), lua, parent)
62    }
63    #[inline]
64    pub fn get_name(&self) -> String {
65        DynInstance::guard_get_name(&self.get_instance_component())
66    }
67    #[inline]
68    pub fn set_name(&self, val: String) -> LuaResult<()> {
69        DynInstance::guard_set_name(&mut self.get_instance_component_mut(), val)
70    }
71    #[inline]
72    pub fn get_archivable(&self) -> bool {
73        DynInstance::guard_get_archivable(&self.get_instance_component())
74    }
75    #[inline]
76    pub fn set_archivable(&self, val: bool) -> LuaResult<()> {
77        DynInstance::guard_set_archivable(&mut self.get_instance_component_mut(), val)
78    }
79    #[inline]
80    pub fn get_uniqueid(&self) -> usize {
81        Self::guard_get_uniqueid(&self.get_instance_component())
82    }
83    #[inline]
84    pub fn init_uniqueid(&self) -> LuaResult<()> {
85        DynInstance::guard_init_uniqueid(&mut self.get_instance_component_mut())
86    }
87    #[inline]
88    pub fn set_uniqueid(&self, value: usize) -> LuaResult<()> {
89        DynInstance::guard_set_uniqueid(&mut self.get_instance_component_mut(), value)
90    }
91    
92    #[inline]
93    pub fn get_ancestors(&self) -> Vec<ManagedInstance> {
94        DynInstance::guard_get_ancestors(&self.get_instance_component())
95    }
96    #[inline]
97    pub fn get_children(&self) -> LuaResult<Vec<ManagedInstance>> {
98        DynInstance::guard_get_children(&self.get_instance_component())
99    }
100    #[inline]
101    pub fn get_descendants(&self) -> LuaResult<Vec<ManagedInstance>> {
102        DynInstance::guard_get_descendants(&self.get_instance_component())
103    }
104    #[inline]
105    pub fn is_ancestor_of(&self, descendant: ManagedInstance) -> LuaResult<bool> {
106        DynInstance::is_ancestor_of_guard_guard(&self.get_instance_component(), &descendant.get_instance_component())
107    }
108    #[inline]
109    pub fn is_descendant_of(&self, ancestor: ManagedInstance) -> LuaResult<bool> {
110        DynInstance::is_ancestor_of_guard_guard(&ancestor.get_instance_component(), &self.get_instance_component())
111    }
112    #[inline]
113    pub fn lock_parent(&self) {
114        DynInstance::guard_lock_parent(&mut self.get_instance_component_mut());
115    }
116    #[inline]
117    pub fn get_parent_protected(&self) -> bool {
118        DynInstance::guard_get_parent_protected(&self.get_instance_component())
119    }
120    #[inline]
121    pub fn clear_all_children(&self, lua: &Lua) -> LuaResult<()> {
122        DynInstance::guard_clear_all_children(&mut self.get_instance_component_mut(), lua)
123    }
124    #[inline]
125    pub fn destroy(&self, lua: &Lua) -> LuaResult<()> {
126        DynInstance::guard_destroy(&mut self.get_instance_component_mut(), lua)
127    }
128
129    
130    pub fn guard_get_parent(this: &impl IReadInstanceComponent) -> Option<ManagedInstance> {
131        let parent = this.parent.as_ref();
132        if parent.is_some() { unsafe {
133            let parent = parent.unwrap_unchecked().upgrade();
134            if parent.is_some() {
135                return Some(parent.unwrap_unchecked())
136            }
137            return None
138        }}
139        None
140    }
141    #[inline]
142    pub fn guard_set_parent(this: &mut WriteInstanceComponent, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
143        if this.parent_locked {
144            Err(LuaError::RuntimeError("Parent property is locked.".into()))
145        } else {
146            DynInstance::set_parent_forced(this, lua, parent)
147        }
148    }
149    fn set_parent_forced(this: &mut WriteInstanceComponent, lua: &Lua, parent: Option<ManagedInstance>) -> LuaResult<()> {
150        // Havent tested roblox's internal order
151        // This internal order is: DescendantRemoving -> ChildRemoved -> AncestryChanged -> ChildAdded -> DescendantAdded
152        if parent.is_some() {
153            let _parent_instance = parent.as_ref().unwrap();
154            let p = _parent_instance.get_instance_component();
155            let this_ptr = this._ptr.as_ref().unwrap().upgrade().unwrap();
156            let _guard_release = this.guard_release();
157            if DynInstance::guard_is_descendant_of(&p, this_ptr)? {
158                return Err(LuaError::RuntimeError("Invalid hierarchy while setting up instance tree.".into()))
159            }
160        }
161        if this.parent.is_some() {
162            // Descendant removing for all ancestors
163            let ancestors = DynInstance::guard_get_ancestors(&*this);
164            let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
165            let _guard_release = this.guard_release();
166            for ancestor in ancestors {
167                ancestor.get_instance_component()
168                    .descendant_removing.write().fire(lua, (_ptr_this.clone(),))?;
169            }
170        }
171
172        let new_parent = parent.clone();
173        let mut old_parent = parent.map(|x| x.downgrade());
174        swap(&mut this.parent, &mut old_parent);
175
176        if old_parent.is_some() {
177            let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
178            let _guard_release = this.guard_release();
179            let old_parent = old_parent.unwrap().upgrade().unwrap();
180            old_parent.get_instance_component_mut().children.retain(|x| *x != _ptr_this);
181            old_parent.get_instance_component().child_removed.write().fire_ancestry(lua, (_ptr_this,))?;
182        }
183
184        let descendants = DynInstance::guard_get_descendants(this)?;
185
186        let _ptr_this = this._ptr.as_ref().unwrap().upgrade().unwrap();
187        let _guard_release = this.guard_release();
188        for i in descendants {
189            i.get_instance_component()
190                .ancestry_changed.write().fire(lua, (_ptr_this.clone(), new_parent.clone()))?;
191        }
192        drop(_guard_release);
193
194        if new_parent.is_some() {
195            let ancestors = DynInstance::guard_get_ancestors(this);
196            let _guard_release = this.guard_release();
197            let new_parent = new_parent.unwrap();
198            new_parent.get_instance_component_mut().children.push(_ptr_this.clone());
199            new_parent.get_instance_component().child_added.write().fire_ancestry(lua, (_ptr_this.clone(),))?;
200            for ancestor in ancestors {
201                ancestor.get_instance_component().descendant_added.write().fire_ancestry(lua, (_ptr_this.clone(),))?;
202            }
203        }
204        Ok(())
205    }
206    pub fn guard_get_name(this: &impl IReadInstanceComponent) -> String {
207        this.name.clone()
208    }
209    pub fn guard_set_name(this: &mut WriteInstanceComponent, val: String) -> LuaResult<()> {
210        this.name = val;
211        Ok(())
212    }
213    pub fn guard_get_archivable(this: &impl IReadInstanceComponent) -> bool {
214        this.archivable
215    }
216    pub fn guard_set_archivable(this: &mut WriteInstanceComponent, val: bool) -> LuaResult<()> {
217        this.archivable = val;
218        Ok(())
219    }
220    pub fn guard_get_uniqueid(this: &impl IReadInstanceComponent) -> usize {
221        this.unique_id
222    }
223    pub fn guard_init_uniqueid(this: &mut WriteInstanceComponent) -> LuaResult<()> {
224        if this.unique_id != 0 {
225            return Err(LuaError::RuntimeError("Instance::UniqueId was previously initialized.".into()));
226        }
227        let mut hasher = DefaultHasher::new();
228        (&raw const *this).hash(&mut hasher);
229        this.unique_id = hasher.finish() as usize;
230        Ok(())
231    }
232    pub fn guard_set_uniqueid(this: &mut WriteInstanceComponent, value: usize) -> LuaResult<()> {
233        if this.unique_id != 0 {
234            return Err(LuaError::RuntimeError("Instance::UniqueId was previously initialized.".into()));
235        }
236        this.unique_id = value;
237        Ok(())
238    }
239    
240    pub fn guard_get_ancestors(this: &impl IReadInstanceComponent) -> Vec<ManagedInstance> {
241        let mut i = this.parent.as_ref().map(|x| x.upgrade()).flatten();
242        let mut vec = Vec::new();
243        while let Some(instance) = i {
244            i = instance.get_parent();
245            vec.push(instance);
246        }
247        vec
248    }
249    pub fn guard_get_children(this: &impl IReadInstanceComponent) -> LuaResult<Vec<ManagedInstance>> {
250        Ok(this.children.clone())
251    }
252    pub fn guard_get_descendants(this: &impl IReadInstanceComponent) -> LuaResult<Vec<ManagedInstance>> {
253        let mut current = DynInstance::guard_get_children(this)?;
254        let mut descendants: Vec<ManagedInstance> = vec![];
255        descendants.append(&mut current);
256        while current.len() != 0 {
257            let mut new_current: Vec<ManagedInstance> = vec![];
258            for i in current {
259                new_current.append(&mut i.get_descendants()?);
260            }
261            descendants.append(&mut new_current);
262            current = new_current;
263        };
264        Ok(descendants)
265    }
266    pub fn guard_lock_parent(this: &mut WriteInstanceComponent) {
267        this.parent_locked = true;
268    }
269    pub fn guard_get_parent_protected(this: &impl IReadInstanceComponent) -> bool {
270        this.parent_locked
271    }
272    pub fn guard_clear_all_children(this: &mut WriteInstanceComponent, lua: &Lua) -> LuaResult<()> {
273        let children = this.children.clone().into_iter();
274        let _guard = this.guard_release();
275        for i in children {
276            let mut instance_write = i.get_instance_component_mut();
277            if !instance_write.parent_locked {
278                DynInstance::guard_destroy(&mut instance_write, lua)?;
279            }
280        }
281        Ok(())
282    }
283    pub fn guard_destroy(this: &mut WriteInstanceComponent, lua: &Lua) -> LuaResult<()> {
284        if this.parent_locked {
285            return Err(LuaError::RuntimeError("Parent property locked.".into()));
286        }
287        {
288            let signal = this.destroying.clone();
289            let destroying = signal.write();
290            
291            let _guard_release = this.guard_release();
292         
293            destroying.fire(lua,())?;
294        }
295        this.parent_locked = true;
296        DynInstance::set_parent_forced(this, lua, None)?;
297        DynInstance::guard_clear_all_children(this, lua)?;
298        Ok(())
299    }
300    #[inline]
301    pub fn guard_is_ancestor_of(this: &impl IReadInstanceComponent, descendant: ManagedInstance) -> LuaResult<bool> {
302        DynInstance::is_ancestor_of_guard_guard(this, &descendant.get_instance_component())
303    }
304    #[inline]
305    pub fn guard_is_descendant_of(this: &impl IReadInstanceComponent, ancestor: ManagedInstance) -> LuaResult<bool> {
306        DynInstance::is_ancestor_of_guard_guard(&ancestor.get_instance_component(), this)
307    }
308    pub fn guard_find_first_ancestor_of_class(this: &impl IReadInstanceComponent, class: String) -> LuaResult<Option<ManagedInstance>> {
309        for i in DynInstance::guard_get_ancestors(this) {
310            if i.get_class_name() == class {
311                return Ok(Some(i));
312            }
313        }
314        Ok(None)
315    }
316    
317    pub fn get_debug_id(&self, _scope_length: LuaNumber) -> LuaResult<String> {
318        Ok(format!("0x{:x}",(&raw const *self.get_instance_component()) as usize))
319    }
320    pub fn get_full_name(&self) -> LuaResult<String> {
321        let mut hierarchy = Vec::new();
322        let mut parent = self.get_parent();
323        while parent.is_some() {
324            let parent_unwrapped = unsafe { parent.unwrap_unchecked() };
325            let parent_read = parent_unwrapped.get_instance_component();
326            hierarchy.insert(0, DynInstance::guard_get_name(&parent_read));
327
328            parent = DynInstance::guard_get_parent(&parent_read);
329        }
330        hierarchy.push(self.get_name());
331        Ok(hierarchy.join("."))
332    }
333    pub fn add_tag(&self, lua: &Lua, tag: String) -> LuaResult<()> {
334        let mut write = self.get_instance_component_mut();
335        let ptr = write._ptr.clone().unwrap();
336        write.tags.insert(tag.clone());
337        drop(write);
338        get_state(lua).get_vm().get_instance_tag_table().add_tag(tag, ptr);
339        Ok(())
340    }
341    
342    pub async fn wait_for_child(&self, lua: &Lua, name: String, timeout: Option<LuaNumber>) -> LuaResult<Option<ManagedInstance>> {
343        let inst = self.find_first_child(name.clone(), Some(false)).unwrap();
344        if inst.is_some() {
345            Ok(Some(unsafe { inst.unwrap_unchecked() }))
346        } else {
347            let thread = lua.current_thread();
348            if timeout.is_some() {
349                get_task_scheduler_from_lua(lua).delay_thread(thread.clone(), ParallelDispatch::Default, timeout.unwrap())?;
350            }
351            let i = self.get_instance_component().child_added.clone();
352            let mut instance: ManagedInstance;
353            loop {
354                let mv = i.read().wait(lua).await?;
355                if mv.is_empty() {
356                    return Ok(None); // timed out
357                }
358                instance = ManagedInstance::from_lua_multi(mv, lua)?;
359                if instance.get_name() == name {
360                    break;
361                }
362            }
363            Ok(Some(instance))
364        }
365    }
366    pub fn find_first_ancestor(&self, name: String) -> LuaResult<Option<ManagedInstance>> {
367        for i in self.get_ancestors() {
368            if i.get_name() == name {
369                return Ok(Some(i));
370            }
371        }
372        Ok(None)
373    }
374    pub fn find_first_ancestor_of_class(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
375        for i in self.get_ancestors() {
376            if i.get_class_name() == class {
377                return Ok(Some(i));
378            }
379        }
380        Ok(None)
381    }
382    pub fn find_first_ancestor_which_is_a(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
383        for i in self.get_ancestors() {
384            if i.is_a(&class) {
385                return Ok(Some(i));
386            }
387        }
388        Ok(None)
389    }
390    pub fn find_first_child(&self, name: String, recursive: Option<bool>) -> LuaResult<Option<ManagedInstance>> {
391        if recursive.unwrap_or(false) {
392            for i in self.get_children()? {
393                if i.get_name() == name {
394                    return Ok(Some(i));
395                }
396            }
397            Ok(None)
398        } else {
399            self.find_first_descendant(name)
400        }
401    }
402    pub fn find_first_child_of_class(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
403        for i in self.get_children()? {
404            if i.get_class_name() == class {
405                return Ok(Some(i));
406            }
407        }
408        Ok(None)
409    }
410    pub fn find_first_child_which_is_a(&self, class: String) -> LuaResult<Option<ManagedInstance>> {
411        for i in self.get_children()? {
412            if i.is_a(&class) {
413                return Ok(Some(i));
414            }
415        }
416        Ok(None)
417    }
418    pub fn find_first_descendant(&self, name: String) -> LuaResult<Option<ManagedInstance>> {
419        for i in self.get_descendants()? {
420            if i.get_name() == name {
421                return Ok(Some(i));
422            }
423        }
424        Ok(None)
425    }
426    pub fn get_attribute(&self, attribute: String) -> LuaResult<LuaValue> {
427        Ok(self.get_instance_component().attributes.get(&attribute).unwrap_or(&LuaNil).clone())
428    }
429    pub fn get_attribute_changed_signal(&self, attribute: String) -> LuaResult<ManagedRBXScriptSignal> {
430        let read = self.get_instance_component();
431        if let Some(event) = read.attribute_changed_table.get(&attribute) {
432            Ok(event.clone())
433        } else {
434            drop(read);
435            let mut write = self.get_instance_component_mut();
436            let event = RBXScriptSignal::new();
437            write.attribute_changed_table.insert(attribute, event.clone());
438            Ok(event)
439        }
440    }
441    pub fn get_attributes(&self, lua: &Lua) -> LuaResult<LuaValue> {
442        self.get_instance_component().attributes.clone().into_lua(lua)
443    }
444    pub fn get_tags(&self) -> LuaResult<Vec<String>> {
445        Ok(self.get_instance_component().tags.iter().map(|x| x.clone()).collect())
446    }
447    pub fn has_tag(&self, tag: String) -> LuaResult<bool> {
448        Ok(self.get_instance_component().tags.get(&tag).is_some())
449    }
450    fn is_ancestor_of_guard_guard(this: &impl IReadInstanceComponent, descendant: &impl IReadInstanceComponent) -> LuaResult<bool> {
451        let mut i = DynInstance::guard_get_parent(descendant);
452        while let Some(ref parent) = i {
453            let read = parent.get_instance_component();
454            if unsafe {read._ptr.as_ref().unwrap_unchecked() == this._ptr.as_ref().unwrap_unchecked()} {
455                return Ok(true);
456            }
457            let new_i = read.parent.as_ref().map(|x| x.upgrade()).flatten();
458            drop(read);
459            i = new_i;
460        }
461        Ok(false)
462    }
463    pub fn remove_tag(&self, lua: &Lua, tag: String) -> LuaResult<()> {
464        let mut write = self.get_instance_component_mut();
465        let ptr = write._ptr.clone().unwrap();
466        write.tags.remove(&tag);
467        drop(write);
468        get_state(lua).get_vm().get_instance_tag_table().remove_tag(tag, &ptr);
469        Ok(())
470    }
471    pub fn set_attribute(&self, lua: &Lua, attribute: String, value: LuaValue) -> LuaResult<()> {
472        let mut write = self.get_instance_component_mut();
473        write.attributes.insert(attribute.clone(), value.clone());
474        let attribute_changed = write.attribute_changed.clone();
475        let attribute_changed_signal = write.attribute_changed_table.get(&attribute).cloned();
476        attribute_changed.write().fire(lua, (attribute,))?;
477        attribute_changed_signal.map(move |x| x.write().fire(lua, (value,))).unwrap_or(Ok(()))
478    }
479    
480}
481
482impl Debug for DynInstance {
483    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
484        f.write_str(&format!("{:x}", &raw const *self as *const u8 as usize))
485    }
486}
487
488#[derive(Debug)]
489pub struct InstanceComponent {
490    archivable: bool,
491    name: String,
492    parent: Option<WeakManagedInstance>,
493    _ptr: Option<WeakManagedInstance>,
494    unique_id: usize,
495    children: Vec<ManagedInstance>,
496    children_cache: HashMap<String, WeakManagedInstance>,
497    children_cache_dirty: bool,
498    parent_locked: bool,
499
500    pub ancestry_changed: ManagedRBXScriptSignal,
501    pub attribute_changed: ManagedRBXScriptSignal,
502    pub changed: ManagedRBXScriptSignal,
503    pub child_added: ManagedRBXScriptSignal,
504    pub child_removed: ManagedRBXScriptSignal,
505    pub descendant_added: ManagedRBXScriptSignal,
506    pub descendant_removing: ManagedRBXScriptSignal,
507    pub destroying: ManagedRBXScriptSignal,
508
509    pub attribute_changed_table: EventsTable,
510    pub property_changed_table: EventsTable,
511
512    attributes: HashMap<String, LuaValue>,
513    tags: HashSet<String>
514}
515
516impl PartialEq for DynInstance {
517    fn eq(&self, other: &Self) -> bool {
518        (&raw const *self) == (&raw const *other)
519    }
520}
521impl Eq for DynInstance {}
522
523impl IInstanceComponent for InstanceComponent {
524    fn lua_get(self: &mut RwLockReadGuard<'_, Self>, _: &DynInstance, lua: &Lua, key: &String) -> Option<LuaResult<LuaValue>> {
525        Some(InstanceComponent::lua_get(self, lua, key))
526    }
527
528    fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, _: &DynInstance, lua: &Lua, key: &String, value: &LuaValue) -> Option<LuaResult<()>> {
529        Some(InstanceComponent::lua_set(self, lua, key, value.clone()))
530    }
531
532    fn new(ptr: WeakManagedInstance, class_name: &'static str) -> Self {
533        let inst = InstanceComponent {
534            parent: None,
535            name: String::from(class_name),
536            archivable: true,
537            unique_id: usize::default(), //uninitialized,
538            _ptr: Some(ptr),
539            parent_locked: false,
540            children: Vec::new(),
541            children_cache: HashMap::new(),
542            children_cache_dirty: false,
543
544            ancestry_changed: RBXScriptSignal::new(),
545            attribute_changed: RBXScriptSignal::new(),
546            changed: RBXScriptSignal::new(),
547            child_added: RBXScriptSignal::new(),
548            child_removed: RBXScriptSignal::new(),
549            descendant_added: RBXScriptSignal::new(),
550            descendant_removing: RBXScriptSignal::new(),
551            destroying: RBXScriptSignal::new(),
552            
553            attribute_changed_table: EventsTable::default(),
554            property_changed_table: EventsTable::default(),
555
556            attributes: HashMap::default(),
557            tags: HashSet::default()
558        };
559        inst
560    }
561    fn clone(self: &RwLockReadGuard<'_, Self>, lua: &Lua, ptr: &WeakManagedInstance) -> LuaResult<Self> {
562        let mut new_children = Vec::new();
563        for i in self.children.iter() {
564            let inst = i.clone_instance(lua);
565            if inst.is_ok() {
566                new_children.push(unsafe { inst.unwrap_unchecked() });
567            }
568        }
569        Ok(InstanceComponent {
570            archivable: self.archivable,
571            name: self.name.clone(),
572            parent: None,
573            unique_id: 0,
574            children: new_children,
575            children_cache: HashMap::default(),
576            children_cache_dirty: true,
577            _ptr: Some(ptr.clone()),
578            parent_locked: false,
579
580            ancestry_changed: RBXScriptSignal::new(),
581            attribute_changed: RBXScriptSignal::new(),
582            changed: RBXScriptSignal::new(),
583            child_added: RBXScriptSignal::new(),
584            child_removed: RBXScriptSignal::new(),
585            descendant_added: RBXScriptSignal::new(),
586            descendant_removing: RBXScriptSignal::new(),
587            destroying: RBXScriptSignal::new(),
588            
589            attribute_changed_table: EventsTable::default(),
590            property_changed_table: EventsTable::default(),
591
592            attributes: self.attributes.clone(),
593            tags: HashSet::default()
594        })
595    }
596
597}
598
599impl InstanceComponent {
600    pub fn get_instance_pointer(self: &RwLockReadGuard<'_, Self>) -> ManagedInstance {
601        unsafe {
602            self._ptr.as_ref().unwrap_unchecked().upgrade().unwrap_unchecked()
603        }
604    }
605    pub fn get_weak_instance_pointer(self: &RwLockReadGuard<'_, Self>) -> WeakManagedInstance {
606        unsafe { self._ptr.as_ref().unwrap_unchecked().clone() }
607    }
608    pub fn lua_get(self: &mut RwLockReadGuard<'_, Self>, lua: &Lua, key: &String) -> LuaResult<LuaValue> {
609        match key.as_str() {
610            "Archivable" => lua_getter!(lua, self.archivable),
611            "ClassName" => IntoLua::into_lua(unsafe { 
612                self._ptr.as_ref().unwrap_unchecked()
613                    .upgrade().unwrap_unchecked().get_class_name()
614                }, lua),
615            "Name" => lua_getter!(string, lua, self.name),
616            "Parent" => lua_getter!(opt_weak_clone, lua, self.parent),
617
618            "AddTag" => lua_getter!(function, lua, 
619                |lua, (this, tag): (ManagedInstance, String)| 
620                    this.add_tag(lua, tag)
621            ),
622            "ClearAllChildren" => lua_getter!(function, lua,
623                |lua, (this, ): (ManagedInstance, )| {
624                    this.clear_all_children(lua)
625                }
626            ),
627            "Clone" => lua_getter!(function, lua,
628                |lua, (this, ): (ManagedInstance, )| 
629                    this.clone_instance(lua)
630            ),
631            "Destroy" => lua_getter!(function, lua,
632                |lua, (this, ): (ManagedInstance, )| {
633                    this.destroy(lua)
634                }
635            ),
636            "FindFirstAncestor" => lua_getter!(function, lua,
637                |_, (this, name): (ManagedInstance, String)| 
638                    this.find_first_ancestor(name)
639            ),
640            "FindFirstAncestorOfClass" => lua_getter!(function, lua,
641                |_, (this, class): (ManagedInstance, String)| 
642                    this.find_first_ancestor_of_class(class)
643            ),
644            "FindFirstAncestorWhichIsA" => lua_getter!(function, lua,
645                |_, (this, class): (ManagedInstance, String)| 
646                    this.find_first_ancestor_which_is_a(class)
647            ),
648            "FindFirstChild" => lua_getter!(function, lua,
649                |_, (this, name, recursive): (ManagedInstance, String, Option<bool>)| 
650                    this.find_first_child(name, recursive)
651            ),
652            "FindFirstChildOfClass" => lua_getter!(function, lua,
653                |_, (this, class): (ManagedInstance, String)| 
654                    this.find_first_child_of_class(class)
655            ),
656            "FindFirstChildWhichIsA" => lua_getter!(function, lua,
657                |_, (this, class): (ManagedInstance, String)| 
658                    this.find_first_ancestor_which_is_a(class)
659            ),
660            "GetActor" => lua_getter!(function, lua,
661                |_, (this,): (ManagedInstance,)| 
662                    this.get_actor()
663            ),
664            "GetAttribute" => lua_getter!(function, lua,
665                |_, (this, name): (ManagedInstance, String)| 
666                    this.get_attribute(name)
667            ),
668            "GetAttributeChangedSignal" => lua_getter!(function, lua,
669                |_, (this, attribute): (ManagedInstance, String)| {
670                    Ok(this.get_attribute_changed_signal(attribute))
671            }),
672            "GetAttributes" => lua_getter!(function, lua,
673                |lua, (this,): (ManagedInstance,)|
674                    this.get_attributes(lua)
675            ),
676            "GetChildren" => lua_getter!(function, lua,
677                |_, (this,): (ManagedInstance,)|
678                    this.get_children()
679            ),
680            "GetDebugId" => lua_getter!(function, lua,
681                |_, (this,scope_len): (ManagedInstance,LuaNumber)|
682                    this.get_debug_id(scope_len)
683            ),
684            "GetDescendants" => lua_getter!(function, lua,
685                |_, (this,): (ManagedInstance,)|
686                    this.get_descendants()
687            ),
688            "GetFullName" => lua_getter!(function, lua,
689                |_, (this,): (ManagedInstance,)|
690                    this.get_full_name()
691            ),
692            "GetStyled" => lua_getter!(function, lua,
693                |_, (_this,): (ManagedInstance,)| {
694                    Err::<(), LuaError>(LuaError::RuntimeError("todo!(): function not yet implemented".into()))
695                }
696            ),
697            "GetTags" => lua_getter!(function, lua,
698                |_, (this,): (ManagedInstance,)|
699                    this.get_tags()
700            ),
701            "HasTag" => lua_getter!(function, lua,
702                |_, (this, tag): (ManagedInstance, String)|
703                    this.has_tag(tag)
704            ),
705            "IsAncestorOf" => lua_getter!(function, lua,
706                |_, (this, inst): (ManagedInstance, ManagedInstance)|
707                    this.is_ancestor_of(inst)
708            ),
709            "IsDescendantOf" => lua_getter!(function, lua,
710                |_, (this, inst): (ManagedInstance, ManagedInstance)|
711                    this.is_descendant_of(inst)
712            ),
713            "RemoveTag" => lua_getter!(function, lua,
714                |lua, (this, tag): (ManagedInstance, String)|
715                    this.remove_tag(lua, tag)
716            ),
717            "SetAttribute" => lua_getter!(function, lua,
718                |lua, (this, attribute, value): (ManagedInstance, String, LuaValue)|
719                    this.set_attribute(lua, attribute, value)
720            ),
721            "WaitForChild" => lua_getter!(function_async, lua,
722                async |lua, (this, child, timeout): (ManagedInstance, String, Option<LuaNumber>)| {
723                    this.wait_for_child(&lua, child, timeout).await
724                }
725            ),
726            
727            "AncestryChanged" => lua_getter!(clone, lua, self.ancestry_changed),
728            "AttributeChanged" => lua_getter!(clone, lua, self.attribute_changed),
729            "ChildAdded" => lua_getter!(clone, lua, self.child_added),
730            "ChildRemoved" => lua_getter!(clone, lua, self.child_removed),
731            "DescendantAdded" => lua_getter!(clone, lua, self.descendant_added),
732            "DescendantRemoving" => lua_getter!(clone, lua, self.descendant_removing),
733            "Destroying" => lua_getter!(clone, lua, self.destroying),
734
735            _ => lua_getter!(lua, self.find_first_child(key))
736        }
737    }
738
739    fn remake_cache(self: &mut RwLockReadGuard<'_, Self>) {
740        let inst = self._ptr.as_ref().map(|x| x.upgrade()).flatten().unwrap();
741        let _release = self.guard_release();
742        let mut write = inst.get_instance_component_mut();
743        
744        let iter: Vec<(String, WeakManagedInstance)> = write.children.iter()
745            .map(|x| (x.get_name(), x.downgrade()))
746            .collect();
747        write.children_cache.clear();
748        for (name, i) in iter {
749            if write.children_cache.get(&name).is_none() {
750                write.children_cache.insert(name, i);
751            }
752        }
753    }
754    fn find_first_child(self: &mut RwLockReadGuard<'_, Self>, key: &String) -> Option<ManagedInstance> {
755        if self.children_cache_dirty {
756            self.remake_cache();
757            self.children_cache.get(key).map(|x| x.upgrade()).flatten()
758        } else {
759            self.children_cache.get(key).map(|x| x.upgrade()).flatten()
760        }
761    }
762    pub fn emit_property_changed(this: &impl IReadInstanceComponent, lua: &Lua, property: &'static str, value: &LuaValue) -> LuaResult<()> {
763        this.changed.write().fire(lua, (property,))?;
764        this.property_changed_table.get(property)
765            .map(|x| x.write().fire(lua, (value,)))
766            .unwrap_or(Ok(()))
767    }
768    pub fn get_property_changed_signal(self: &mut RwLockReadGuard<'_, Self>, property: String) -> LuaResult<ManagedRBXScriptSignal> {
769        let read = self.property_changed_table.get(&property);
770        if read.is_some() {
771            Ok(read.unwrap().clone())
772        } else {
773            let inst = self._ptr.as_ref().map(|x| x.upgrade()).flatten().unwrap();
774            let _release = self.guard_release();
775            
776            let mut write = inst.get_instance_component_mut();
777            let signal = RBXScriptSignal::new();
778            write.property_changed_table.insert(property, signal.clone());
779            Ok(signal)
780        }
781    }
782
783    pub fn lua_set(self: &mut RwLockWriteGuard<'_, Self>, lua: &Lua, key: &String, value: LuaValue) -> LuaResult<()> {
784        match key.as_str() {
785            "Archivable" => {
786                self.archivable = value.as_boolean().ok_or(LuaError::RuntimeError("bad argument to setting Archivable".into()))?;
787                Self::emit_property_changed(self, lua, "Archivable", &value)
788            },
789            "Name" => {
790                self.name = value.as_string_lossy().ok_or(LuaError::RuntimeError("bad argument to setting Name".into()))?;
791                Self::emit_property_changed(self, lua, "Name", &value)
792            },
793            "Parent" => {
794                DynInstance::guard_set_parent(self, lua, FromLua::from_lua(value, lua)?)
795            },
796            _ => Err(LuaError::RuntimeError(format!("can't set property {} on object of type Instance",key.as_str())))
797        }
798    }
799}
800
801impl<T: IInstance, A: Allocator + Clone + Send + Sync> IWeak<T, A> {
802    pub fn cast_to_instance(&self) -> IWeak<DynInstance, A> {
803        let (header_raw, p_raw, alloc) = self.clone().into_inner_with_allocator();
804        let p = p_raw as *mut DynInstance;
805        let header = unsafe { NonNull::new_unchecked(header_raw.as_ptr() as *mut IrcHead<DynInstance>) };
806        IWeak::from_inner_with_allocator((header, p, alloc))
807    }
808}