1#![allow(clippy::not_unsafe_ptr_arg_deref)] pub use rrplug_proc::{GetFromSQObject, GetFromSquirrelVm, PushToSquirrelVm, SQVMName};
6use std::{mem::MaybeUninit, ptr::NonNull};
7
8use crate::{
9 bindings::{
10 class_types::{cbaseentity::CBaseEntity, cplayer::CPlayer},
11 squirrelclasstypes::SQRESULT,
12 squirreldatatypes::{
13 SQArray, SQBool, SQClosure, SQFloat, SQFunctionProto, SQInteger, SQNativeClosure,
14 SQObject, SQObjectType, SQObjectValue, SQString, SQStructInstance, SQTable,
15 },
16 },
17 high::squirrel::SQHandle,
18 mid::{
19 squirrel::{
20 get_sq_array, get_sq_bool, get_sq_float, get_sq_int, get_sq_object, get_sq_string,
21 get_sq_vector, push_sq_array, push_sq_bool, push_sq_float, push_sq_int, push_sq_object,
22 push_sq_string, push_sq_vector, sqvm_to_context,
23 },
24 utils::to_cstring,
25 },
26 prelude::*,
27};
28
29use super::UnsafeHandle;
30
31macro_rules! push_to_sqvm {
34 ( $( $function:ident::<$t:ty> );*; ) => { $(
35
36 impl PushToSquirrelVm for $t {
37 #[inline]
38 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
39 $function(sqvm, sqfunctions, self)
40 }
41 }
42 )* }
43}
44
45pub trait PushToSquirrelVm {
51 #[doc(hidden)]
53 const DEFAULT_RESULT: SQRESULT = SQRESULT::SQRESULT_NOTNULL;
54
55 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions);
57}
58
59push_to_sqvm! {
60 push_sq_string::<String>;
61 push_sq_string::<&str>;
62 push_sq_int::<i32>;
63 push_sq_float::<f32>;
64 push_sq_bool::<bool>;
65 push_sq_vector::<Vector3>;
66 push_sq_object::<SQObject>;
67}
68
69impl<T> PushToSquirrelVm for Vec<T>
70where
71 T: PushToSquirrelVm,
72{
73 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
74 push_sq_array(sqvm, sqfunctions, self);
75 }
76}
77
78impl PushToSquirrelVm for () {
79 const DEFAULT_RESULT: SQRESULT = SQRESULT::SQRESULT_NULL;
80
81 #[inline]
82 fn push_to_sqvm(self, _: NonNull<HSquirrelVM>, _: &SquirrelFunctions) {}
83}
84
85impl PushToSquirrelVm for &CPlayer {
86 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
88 unsafe {
89 let obj =
90 (sqfunctions.sq_create_script_instance)((self as *const CPlayer).cast_mut().cast());
91 (sqfunctions.sq_pushobject)(sqvm.as_ptr(), obj);
92 }
93 }
94}
95
96impl PushToSquirrelVm for &CBaseEntity {
97 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
99 unsafe {
100 let obj = (sqfunctions.sq_create_script_instance)(
101 (self as *const CBaseEntity).cast_mut().cast(),
102 );
103 (sqfunctions.sq_pushobject)(sqvm.as_ptr(), obj);
104 }
105 }
106}
107
108impl<T: PushToSquirrelVm, const N: usize> PushToSquirrelVm for [T; N] {
109 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
110 push_sq_array(sqvm, sqfunctions, self);
111 }
112}
113
114impl<T: PushToSquirrelVm> PushToSquirrelVm for UnsafeHandle<T>
115where
116 T: PushToSquirrelVm,
117{
118 fn push_to_sqvm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) {
119 self.take().push_to_sqvm(sqvm, sqfunctions)
120 }
121}
122
123pub trait ReturnToVm {
133 fn return_to_vm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) -> SQRESULT;
135}
136
137impl<T: PushToSquirrelVm> ReturnToVm for Option<T> {
138 fn return_to_vm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) -> SQRESULT {
140 match self {
141 Some(rtrn) => {
142 rtrn.push_to_sqvm(sqvm, sqfunctions);
143 T::DEFAULT_RESULT
144 }
145 None => {
146 unsafe { (sqfunctions.sq_pushnull)(sqvm.as_ptr()) };
147 SQRESULT::SQRESULT_NULL
148 }
149 }
150 }
151}
152
153impl<T: PushToSquirrelVm, E: ToString> ReturnToVm for Result<T, E> {
154 fn return_to_vm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) -> SQRESULT {
158 match self {
159 Ok(rtrn) => {
160 rtrn.push_to_sqvm(sqvm, sqfunctions);
161 T::DEFAULT_RESULT
162 }
163 Err(err) => {
164 let err = to_cstring(err.to_string().as_str());
165 unsafe { (sqfunctions.sq_raiseerror)(sqvm.as_ptr(), err.as_ptr()) };
166 SQRESULT::SQRESULT_ERROR
167 }
168 }
169 }
170}
171
172impl<T: PushToSquirrelVm> ReturnToVm for T {
173 fn return_to_vm(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &SquirrelFunctions) -> SQRESULT {
175 self.push_to_sqvm(sqvm, sqfunctions);
176 T::DEFAULT_RESULT
177 }
178}
179
180pub trait IntoSquirrelArgs {
184 fn into_function(
186 self,
187 ) -> Box<
188 dyn FnOnce(NonNull<HSquirrelVM>, &'static SquirrelFunctions) -> i32 + 'static + Send + Sync,
189 >
190 where
191 Self: Sized + Send + Sync + 'static,
192 {
193 Box::new(
194 move |sqvm: NonNull<HSquirrelVM>, sqfunctions: &'static SquirrelFunctions| {
195 self.into_push(sqvm, sqfunctions)
196 },
197 )
198 }
199
200 fn into_push(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &'static SquirrelFunctions) -> i32;
202}
203
204impl<T: PushToSquirrelVm> IntoSquirrelArgs for T {
205 fn into_push(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &'static SquirrelFunctions) -> i32 {
206 if T::DEFAULT_RESULT != SQRESULT::SQRESULT_NULL {
209 self.push_to_sqvm(sqvm, sqfunctions);
210 1
211 } else {
212 0
213 }
214 }
215}
216
217macro_rules! into_squirrel_args_impl{
219 ( $( ($($ty_name: ident : $tuple_index:tt),*) );*; ) => { $(
220 impl<$($ty_name: PushToSquirrelVm,)*> IntoSquirrelArgs for ($($ty_name,)*) {
221 fn into_push(self, sqvm: NonNull<HSquirrelVM>, sqfunctions: &'static SquirrelFunctions) -> i32 {
222 $(
223 self.$tuple_index.push_to_sqvm(sqvm, sqfunctions);
224 )*
225 $crate::macros::sq_utils::__arg_count_helper([$($crate::__replace_expr!($ty_name)),*]) as i32
226 }
227 }
228 )* }
229}
230
231into_squirrel_args_impl! {
232 (T1: 0);
233 (T1: 0, T2: 1);
234 (T1: 0, T2: 1, T3: 2);
235 (T1: 0, T2: 1, T3: 2, T4: 3);
236 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4);
237 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5);
238 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6);
239 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7);
240 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7, T9: 8);
241 (T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7, T9: 8, T10: 9);
242}
243
244macro_rules! get_from_sqvm {
247 ( $( $function:ident::<$t:ty> );*; ) => { $(
248
249 impl GetFromSquirrelVm for $t {
250 #[inline]
251 fn get_from_sqvm(
252 sqvm: NonNull<HSquirrelVM>,
253 sqfunctions: &SquirrelFunctions,
254 stack_pos: i32,
255 ) -> Self {
256 $function(sqvm, sqfunctions, stack_pos)
257 }
258 }
259 )* };
260
261 ( $( ($($ty_name: ident : $var_name:ident),*) );*; ) => { $(
262 impl<$($ty_name: PushToSquirrelVm,)*> GetFromSquirrelVm for Box<dyn Fn($($ty_name,)*)> {
263 fn get_from_sqvm(
264 sqvm: NonNull<HSquirrelVM>,
265 sqfunctions: &'static SquirrelFunctions,
266 stack_pos: i32,
267 ) -> Self {
268 Box::new(move |$($var_name: $ty_name,)*| { _ =
269 call_sq_object_function!(
270 sqvm,
271 sqfunctions,
272 SQHandle::<SQClosure>::get_from_sqvm(sqvm, sqfunctions, stack_pos),
273 $($var_name),*
274 );
275 })
276 }
277 }
278 )* }
279}
280
281pub trait GetFromSquirrelVm: Sized {
286 fn get_from_sqvm(
291 sqvm: NonNull<HSquirrelVM>,
292 sqfunctions: &'static SquirrelFunctions,
293 stack_pos: i32,
294 ) -> Self;
295
296 #[doc(hidden)]
300 #[inline]
301 fn get_from_sqvm_internal(
302 sqvm: NonNull<HSquirrelVM>,
303 sqfunctions: &'static SquirrelFunctions,
304 stack_pos: &mut i32,
305 ) -> Self {
306 let s = Self::get_from_sqvm(sqvm, sqfunctions, *stack_pos);
307
308 *stack_pos += 1;
311
312 s
313 }
314}
315
316get_from_sqvm! {
317 get_sq_string::<String>;
318 get_sq_int::<i32>;
319 get_sq_float::<f32>;
320 get_sq_bool::<bool>;
321 get_sq_vector::<Vector3>;
322 get_sq_object::<SQObject>;
323}
324
325impl<T> GetFromSquirrelVm for Vec<T>
326where
327 T: GetFromSQObject,
328{
329 fn get_from_sqvm(
330 sqvm: NonNull<HSquirrelVM>,
331 _: &'static SquirrelFunctions,
332 stack_pos: i32,
333 ) -> Self {
334 get_sq_array(sqvm, stack_pos)
335 }
336}
337
338impl GetFromSquirrelVm for Option<&mut CPlayer> {
339 fn get_from_sqvm(
340 mut sqvm: NonNull<HSquirrelVM>,
341 sqfunctions: &SquirrelFunctions,
342 stack_pos: i32,
343 ) -> Self {
344 unsafe {
345 debug_assert_eq!(
346 sqvm_to_context(sqvm),
347 ScriptContext::SERVER,
348 "CPlayer only exists on server vm use C_Player for CLIENT and UI"
349 );
350
351 let sqvm = sqvm.as_mut();
352 let cs_sqvm = sqvm
353 .sharedState
354 .as_ref()
355 .expect("shared state was invalid")
356 .cSquirrelVM;
357
358 let mut obj = MaybeUninit::<SQObject>::uninit();
359 (sqfunctions.sq_getobject)(sqvm, stack_pos, obj.as_mut_ptr());
360
361 (sqfunctions.sq_getentityfrominstance)(
362 cs_sqvm,
363 obj.as_mut_ptr(),
364 (sqfunctions.sq_get_entity_constant_cbase_entity)(),
365 )
366 .cast::<CBaseEntity>()
367 .as_mut()?
368 .dynamic_cast_mut()
369 }
370 }
371}
372
373impl GetFromSquirrelVm for Option<&mut CBaseEntity> {
374 fn get_from_sqvm(
375 mut sqvm: NonNull<HSquirrelVM>,
376 sqfunctions: &SquirrelFunctions,
377 stack_pos: i32,
378 ) -> Self {
379 unsafe {
380 debug_assert_eq!(
381 sqvm_to_context(sqvm),
382 ScriptContext::SERVER,
383 "CBaseEnity only exists on server vm"
384 );
385
386 let sqvm = sqvm.as_mut();
387 let cs_sqvm = sqvm
388 .sharedState
389 .as_ref()
390 .expect("shared state was invalid")
391 .cSquirrelVM;
392
393 let mut obj = MaybeUninit::<SQObject>::uninit();
394 (sqfunctions.sq_getobject)(sqvm, stack_pos, obj.as_mut_ptr());
395
396 let ent = (sqfunctions.sq_getentityfrominstance)(
397 cs_sqvm,
398 obj.as_mut_ptr(),
399 (sqfunctions.sq_get_entity_constant_cbase_entity)(),
400 )
401 .cast::<CBaseEntity>()
402 .as_mut()?;
403
404 Some(ent)
405 }
406 }
407}
408
409impl<'a, T: IsSQObject<'a>> GetFromSquirrelVm for SQHandle<'a, T> {
410 fn get_from_sqvm(
411 sqvm: NonNull<HSquirrelVM>,
412 sqfunctions: &SquirrelFunctions,
413 stack_pos: i32,
414 ) -> Self {
415 unsafe {
416 let mut obj = std::mem::MaybeUninit::<SQObject>::uninit();
417 (sqfunctions.sq_getobject)(sqvm.as_ptr(), stack_pos, obj.as_mut_ptr());
418
419 match Self::try_new(obj.assume_init()) {
420 Ok(handle) => handle,
421 Err(_) => {
422 panic!(
423 "the object wasn't the correct type got {:X} expected {}",
424 obj.assume_init()._Type as i32,
425 std::any::type_name::<T>()
426 );
427 }
428 }
429 }
430 }
431}
432
433impl<T: IntoSquirrelArgs> GetFromSquirrelVm for SquirrelFn<'_, T> {
434 #[inline]
435 fn get_from_sqvm(
436 sqvm: NonNull<HSquirrelVM>,
437 sqfunctions: &'static SquirrelFunctions,
438 stack_pos: i32,
439 ) -> Self {
440 SquirrelFn {
441 func: GetFromSquirrelVm::get_from_sqvm(sqvm, sqfunctions, stack_pos),
442 phantom: std::marker::PhantomData,
443 }
444 }
445}
446
447impl GetFromSquirrelVm for () {
448 fn get_from_sqvm(_: NonNull<HSquirrelVM>, _: &SquirrelFunctions, _: i32) -> Self {}
450}
451
452pub trait GetFromSQObject {
463 fn get_from_sqobject(obj: &SQObject) -> Self;
467}
468
469impl GetFromSQObject for () {
470 #[inline]
471 fn get_from_sqobject(_: &SQObject) -> Self {}
472}
473
474impl GetFromSQObject for String {
475 #[inline]
476 fn get_from_sqobject(obj: &SQObject) -> Self {
477 unsafe {
478 std::ffi::CStr::from_ptr(
479 (&obj._VAL.asString.as_ref().unwrap_unchecked()._val) as *const i8,
480 )
481 .to_string_lossy()
482 .into()
483 }
484 }
485}
486
487impl GetFromSQObject for i32 {
488 #[inline]
489 fn get_from_sqobject(obj: &SQObject) -> Self {
490 unsafe { obj._VAL.asInteger }
491 }
492}
493
494impl GetFromSQObject for f32 {
495 #[inline]
496 fn get_from_sqobject(obj: &SQObject) -> Self {
497 unsafe { obj._VAL.asFloat }
498 }
499}
500
501impl GetFromSQObject for bool {
502 #[inline]
503 fn get_from_sqobject(obj: &SQObject) -> Self {
504 unsafe { obj._VAL.asInteger != 0 }
505 }
506}
507
508impl GetFromSQObject for Vector3 {
509 #[inline]
510 fn get_from_sqobject(obj: &SQObject) -> Self {
511 (obj as *const SQObject).into()
512 }
513}
514
515impl GetFromSQObject for SQObject {
516 #[inline]
517 fn get_from_sqobject(obj: &SQObject) -> Self {
518 *obj
519 }
520}
521
522impl<'a, T: IsSQObject<'a>> GetFromSQObject for SQHandle<'a, T> {
523 #[inline]
524 fn get_from_sqobject(obj: &SQObject) -> Self {
525 match Self::try_new(*obj) {
526 Ok(handle) => handle,
527 Err(_) => {
528 panic!(
529 "the object wasn't the correct type got {:X} expected {}",
530 obj._Type as i32,
531 std::any::type_name::<T>()
532 );
533 }
534 }
535 }
536}
537
538impl<T: IntoSquirrelArgs> GetFromSQObject for SquirrelFn<'_, T> {
539 #[inline]
540 fn get_from_sqobject(obj: &SQObject) -> Self {
541 SquirrelFn {
542 func: SQHandle::try_new(obj.to_owned())
543 .expect("the squirrel object wasn't a function lol L"),
544 phantom: std::marker::PhantomData,
545 }
546 }
547}
548
549impl<T> GetFromSQObject for Vec<T>
550where
551 T: GetFromSQObject,
552{
553 #[inline]
554 fn get_from_sqobject(obj: &SQObject) -> Self {
555 unsafe {
556 let array = obj
557 ._VAL
558 .asArray
559 .as_ref()
560 .expect("the sq object may be invalid");
561
562 (0..array._usedSlots as usize)
563 .map(|i| array._values.add(i))
564 .filter_map(|obj| obj.as_ref())
565 .map(T::get_from_sqobject)
566 .collect()
567 }
568 }
569}
570
571macro_rules! sqvm_name {
574 ($( ($($ty_name:ident : $var_name:ident),*) );*;) => {
575 $(
576 impl<$($ty_name: SQVMName,)*> SQVMName for ($($ty_name,)*) {
577 fn get_sqvm_name() -> String {
578 let mut name = String::new();
579
580 $(
581 if !name.is_empty() { name.push(',');
583 name.push(' ');
584 }
585 name.push_str(&$ty_name::get_sqvm_name());
586 )*
587
588 name
589 }
590 }
591 )*
592 };
593
594 ( $( $t:ty = $sqty:literal );*; ) => {
595 $(
596 impl SQVMName for $t {
597 #[inline]
598 fn get_sqvm_name() -> String {
599 $sqty.to_string()
600 }
601 }
602 )*
603 };
604
605 ( $( LIFE $t:ty = $sqty:literal );*; ) => {
606 $(
607 impl<'a> SQVMName for $t {
608 #[inline]
609 fn get_sqvm_name() -> String {
610 $sqty.to_string()
611 }
612 }
613 )*
614 };
615}
616
617pub trait SQVMName {
624 fn get_sqvm_name() -> String;
628}
629
630sqvm_name! {
631 String = "string";
632 &str = "string";
633 i32 = "int";
634 f32 = "float";
635 bool = "bool";
636 Vector3 = "vector";
637 Option<&mut CPlayer> = "entity";
638 Option<&mut CBaseEntity> = "entity";
639 SQObject = "var";
640 () = "void";
641}
642
643sqvm_name! {
644 LIFE SQHandle<'a, SQClosure> = "var";
645 LIFE SQHandle<'a, SQTable> = "table";
646 LIFE SQHandle<'a, SQString> = "string";
647 LIFE SQHandle<'a, SQArray> = "array";
648 LIFE SQHandle<'a, SQFloat> = "float";
649 LIFE SQHandle<'a, SQInteger> = "int";
650 LIFE SQHandle<'a, SQFunctionProto> = "var";
651 LIFE SQHandle<'a, SQStructInstance> = "var";
652 LIFE SQHandle<'a, SQBool> = "bool";
653 LIFE SQHandle<'a, SQNativeClosure> = "var";
654}
655
656sqvm_name! {
657 (T1: v2);
658 (T1: v1, T2: v2);
659 (T1: v1, T2: v2, T3: v3);
660 (T1: v1, T2: v2, T3: v3, T4: v4);
661 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5);
662 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5, T6: v6);
663 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5, T6: v6, T7: v7);
664 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5, T6: v6, T7: v7, T8: v8);
665 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5, T6: v6, T7: v7, T8: v8, T9: v9);
666 (T1: v1, T2: v2, T3: v3, T4: v4, T5: v5, T6: v6, T7: v7, T8: v8, T9: v9, T10: v10);
667}
668
669impl<T: SQVMName + IntoSquirrelArgs> SQVMName for SquirrelFn<'_, T> {
670 fn get_sqvm_name() -> String {
671 format!("void functionref({})", T::get_sqvm_name())
672 }
673}
674
675impl<T: SQVMName> SQVMName for Vec<T> {
676 fn get_sqvm_name() -> String {
677 format!("array<{}>", T::get_sqvm_name())
678 }
679}
680
681impl<T: SQVMName> SQVMName for Option<T> {
683 fn get_sqvm_name() -> String {
684 format!("{} ornull", T::get_sqvm_name())
685 }
686}
687
688impl<T: SQVMName, E> SQVMName for Result<T, E> {
689 fn get_sqvm_name() -> String {
690 T::get_sqvm_name() }
692}
693
694macro_rules! is_sq_object {
704 ( $( $object:ty,RT: $rt:expr,OT: $ot:expr, EXTRACT: * $extract:ident );*; ) => {
705 $(
706 impl<'a> IsSQObject<'a> for $object {
707 const OT_TYPE: SQObjectType = $ot;
708 const RT_TYPE: SQObjectType = $rt;
709
710 fn extract_mut(val: &'a mut SQObjectValue) -> &'a mut Self {
711 unsafe { &mut *val.$extract } }
713
714 fn extract(val: &'a SQObjectValue) -> &'a Self {
715 unsafe { &*val.$extract } }
717 }
718 )*
719 };
720
721 ( $( $object:ty,RT: $rt:expr,OT: $ot:expr, EXTRACT: $extract:ident );*; ) => {
722 $(
723 impl<'a> IsSQObject<'a> for $object {
724 const OT_TYPE: SQObjectType = $ot;
725 const RT_TYPE: SQObjectType = $rt;
726
727 fn extract_mut(val: &'a mut SQObjectValue) -> &'a mut Self {
728 unsafe { std::mem::transmute(&mut val.$extract) } }
730
731 fn extract(val: &'a SQObjectValue) -> &'a Self {
732 unsafe { std::mem::transmute(&val.$extract) } }
734 }
735 )*
736 }
737}
738
739pub trait IsSQObject<'a> {
741 const OT_TYPE: SQObjectType;
743 const RT_TYPE: SQObjectType;
745
746 fn extract(val: &'a SQObjectValue) -> &'a Self;
750
751 fn extract_mut(val: &'a mut SQObjectValue) -> &'a mut Self;
755}
756
757is_sq_object! {
758 SQTable, RT: SQObjectType::RT_TABLE, OT: SQObjectType::OT_TABLE, EXTRACT: * asTable;
759 SQString, RT: SQObjectType::RT_STRING, OT: SQObjectType::OT_STRING, EXTRACT: * asString;
760 SQFunctionProto, RT: SQObjectType::RT_FUNCPROTO, OT: SQObjectType::OT_FUNCPROTO, EXTRACT: * asFuncProto;
761 SQClosure, RT: SQObjectType::RT_CLOSURE, OT: SQObjectType::OT_CLOSURE, EXTRACT: * asClosure;
762 SQStructInstance, RT: SQObjectType::RT_INSTANCE, OT: SQObjectType::OT_INSTANCE, EXTRACT: * asStructInstance;
763 SQNativeClosure, RT: SQObjectType::RT_NATIVECLOSURE, OT: SQObjectType::OT_NATIVECLOSURE, EXTRACT: * asNativeClosure;
764 SQArray, RT: SQObjectType::RT_ARRAY, OT: SQObjectType::OT_ARRAY, EXTRACT: * asArray;
765}
766is_sq_object! {
767 SQFloat, RT: SQObjectType::RT_FLOAT, OT: SQObjectType::OT_FLOAT, EXTRACT: asFloat;
768 SQInteger, RT: SQObjectType::RT_INTEGER, OT: SQObjectType::OT_INTEGER, EXTRACT: asInteger;
769 SQBool, RT: SQObjectType::RT_BOOL, OT: SQObjectType::OT_BOOL, EXTRACT: asInteger;
770}