From d2cb2dc8b926ed95794986cca8ccf88c3af4b6ea Mon Sep 17 00:00:00 2001 From: fireboltofdeath <24422634+Fireboltofdeath@users.noreply.github.com> Date: Mon, 12 Dec 2022 14:32:20 -0500 Subject: [PATCH 1/5] wip --- build/codegen/luau/mod.rs | 35 +- build/codegen/rust/mod.rs | 20 +- build/codegen/structs/generation.rs | 1 + build/codegen/structs/layout.rs | 5 +- build/dump/mod.rs | 1 + examples/test.rs | 18 +- roblox/abi.luau | 1002 +++++++++++++++++++-------- roblox/init.server.luau | 89 ++- roblox/util.luau | 14 +- src/futures/ffi.rs | 88 +++ src/futures/mod.rs | 11 + src/futures/task.rs | 61 ++ src/futures/waker.rs | 31 + src/lib.rs | 4 + src/libraries/task.rs | 8 +- 15 files changed, 1078 insertions(+), 310 deletions(-) create mode 100644 src/futures/ffi.rs create mode 100644 src/futures/mod.rs create mode 100644 src/futures/task.rs create mode 100644 src/futures/waker.rs diff --git a/build/codegen/luau/mod.rs b/build/codegen/luau/mod.rs index f416590..f55f56d 100644 --- a/build/codegen/luau/mod.rs +++ b/build/codegen/luau/mod.rs @@ -99,11 +99,12 @@ fn generate_member(out: &mut Vec, namespace: &Namespace, member: &Member &mut effect_prereqs, ); + let is_async = member.flags.yielding; let layout = TypeLayout::from_tuple(&member.outputs); let effect = if layout.width() == 0 { effect } else { - if layout.needs_spill() { + if layout.needs_spill() && !is_async { parameters.insert(0, "output".to_string()); } @@ -137,12 +138,32 @@ fn generate_member(out: &mut Vec, namespace: &Namespace, member: &Member .flat_map(|(i, kind)| convert_luau_to_rust(&ids, &names[i], kind, &mut prereqs, false)) .collect(); - let stores = store_memory_or_return(layout, "output", &results); + if is_async { + let addr = ids.next_names(&["output_addr"]); + let future = ids.next_names(&["future"]); + let size = layout.size(); + + let stores = store_memory(layout, &addr, &results); + + Stream::expression(|stream| { + note!(stream, "local {future} = createPointer(0);"); + push!(stream, "task.spawn(function()"); + note!(stream in prereqs); + note!(stream, "local {addr} = allocVec({size});"); + note!(stream, "{stores}"); + note!(stream, "updatePointer({future}, {addr});"); + note!(stream, "wakeFuture({future});"); + pull!(stream, "end)"); + note!(stream, "return {future};"); + }) + } else { + let stores = store_memory_or_return(layout, "output", &results); - Stream::expression(|stream| { - note!(stream in prereqs); - note!(stream, "{stores}"); - }) + Stream::expression(|stream| { + note!(stream in prereqs); + note!(stream, "{stores}"); + }) + } }; Stream::prereq(out, |stream| { @@ -166,6 +187,7 @@ fn generate_abi_start() -> String { let paths = vec![ ("getPointer", "util.getPointer"), ("createPointer", "util.createPointer"), + ("updatePointer", "util.updatePointer"), ("memory", "wasm.memory_list.memory"), ("storeU8", "rt.store.i32_n8"), ("storeU32", "rt.store.i32"), @@ -179,6 +201,7 @@ fn generate_abi_start() -> String { ("functions", "wasm.table_list.__indirect_function_table"), ("invokeFunction", "util.invokeFunction"), ("dropFunctionRef", "util.dropFunctionRef"), + ("wakeFuture", "wasm.func_list.rors_wake_future"), ]; Stream::expression(|stream| { diff --git a/build/codegen/rust/mod.rs b/build/codegen/rust/mod.rs index 1ca8b3a..f284d38 100644 --- a/build/codegen/rust/mod.rs +++ b/build/codegen/rust/mod.rs @@ -57,7 +57,11 @@ fn generate_body(namespace: &Namespace, member: &Member) -> String { let inputs = inputs.join(", "); let has_output = !member.outputs.is_empty(); - let expression = format!("{ffi_name}({inputs})"); + let expression = if member.flags.yielding && has_output { + format!("{ffi_name}({inputs}).await") + } else { + format!("{ffi_name}({inputs})") + }; if has_output { let transformation = owned_ffi_to_rust(&expression, &member.outputs[0]); @@ -80,6 +84,7 @@ fn get_declaration_functions(is_extern: bool) -> DeclarationFunctions { fn generate_member_declaration(member: &Member, name: &str, context: DeclarationContext) -> String { let is_extern = matches!(context, DeclarationContext::Extern); + let is_async = member.flags.yielding; let (get_owned_type, get_borrowed_type) = get_declaration_functions(is_extern); let name = raw_name(name); @@ -117,9 +122,19 @@ fn generate_member_declaration(member: &Member, name: &str, context: Declaration write_to!(stream, "pub "); } + if is_async && !is_extern { + write_to!(stream, "async "); + } + write_to!(stream, "fn {name}({parameters})"); - if outputs.len() > 1 { + if is_async && is_extern { + if outputs.len() > 1 { + write_to!(stream, " -> LuaFuture<({return_types})>"); + } else if !outputs.is_empty() { + write_to!(stream, " -> LuaFuture<{return_types}>"); + } + } else if outputs.len() > 1 { write_to!(stream, " -> ({return_types})"); } else if !outputs.is_empty() { write_to!(stream, " -> {return_types}"); @@ -225,6 +240,7 @@ pub fn generate(namespaces: &[Namespace], enums: &[Enum]) -> String { let mut output = Vec::new(); output.push(generate_extern(namespaces)); output.push("use super::*;".to_string()); + output.push("use crate::futures::ffi::LuaFuture;".to_string()); generate_constant(&mut output); generate_enums(&mut output, enums); diff --git a/build/codegen/structs/generation.rs b/build/codegen/structs/generation.rs index 9dc824c..fde85d4 100644 --- a/build/codegen/structs/generation.rs +++ b/build/codegen/structs/generation.rs @@ -63,6 +63,7 @@ impl Parameter { #[derive(Default)] pub struct MemberFlags { pub deprecated: bool, + pub yielding: bool, pub operator: Option<&'static str>, } diff --git a/build/codegen/structs/layout.rs b/build/codegen/structs/layout.rs index 1b2a239..121f6f0 100644 --- a/build/codegen/structs/layout.rs +++ b/build/codegen/structs/layout.rs @@ -76,7 +76,10 @@ impl TypeLayout { /// Returns the size with an alignment of 4 bytes pub fn size(&self) -> u32 { - align_to_usize(self.representation.iter().map(|v| self.size_of(v)).sum()) + self.representation + .iter() + .map(|v| align_to_usize(self.size_of(v))) + .sum() } pub fn iter(&self) -> impl Iterator { diff --git a/build/dump/mod.rs b/build/dump/mod.rs index 93dfa77..572f8fd 100644 --- a/build/dump/mod.rs +++ b/build/dump/mod.rs @@ -225,6 +225,7 @@ fn transform_class_function( Some(Member { flags: MemberFlags { deprecated: function.tags.contains("Deprecated"), + yielding: function.tags.contains("Yields") || function.tags.contains("CanYield"), ..MemberFlags::default() }, implementation: implementations::Method.into(), diff --git a/examples/test.rs b/examples/test.rs index 9a6d0b8..ba5707c 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -10,6 +10,22 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; /// # Safety #[allow(unreachable_code)] pub fn main() { + futures::spawn(async { + loop { + let time = task::wait(4.0).await; + println!("spawned async? took {time}"); + + println!("now waiting for a part to be added!"); + let instance = Workspace::instance() + .wait_for_child("a child", 69420.0) + .await; + println!( + "waited for instance, got {:?}", + instance.map(|v| v.get_full_name()) + ); + } + }); + let x = "wow!!!"; let fnn1 = move || { println!("Wow, hello {}!", x); @@ -28,7 +44,7 @@ pub fn main() { let value = "Workspace".to_string(); let connection = Workspace::instance().on_instance_changed(|name| { - println!("On instance changed!!!, {}", name); + // println!("On instance changed!!!, {}", name); }); task::delay(4.0, move || { diff --git a/roblox/abi.luau b/roblox/abi.luau index ab6222e..6d17238 100644 --- a/roblox/abi.luau +++ b/roblox/abi.luau @@ -1,5 +1,5 @@ local abi = { ffi = {} }; -local getPointer, createPointer, memory, storeU8, storeU32, storeFloat, loadU8, loadU32, loadFloat, loadString, allocString, allocVec, functions, invokeFunction, dropFunctionRef; +local getPointer, createPointer, updatePointer, memory, storeU8, storeU32, storeFloat, loadU8, loadU32, loadFloat, loadString, allocString, allocVec, functions, invokeFunction, dropFunctionRef, wakeFuture; local connections = {}; local function createConnection(stack, vtable, connection) local id = createPointer(connection); @@ -7,7 +7,7 @@ local function createConnection(stack, vtable, connection) return id; end function abi.load(wasm, rt, util) - getPointer, createPointer, memory, storeU8, storeU32, storeFloat, loadU8, loadU32, loadFloat, loadString, allocString, allocVec, functions, invokeFunction, dropFunctionRef = util.getPointer, util.createPointer, wasm.memory_list.memory, rt.store.i32_n8, rt.store.i32, rt.store.f64, rt.load.i32_u8, rt.load.i32, rt.load.f64, rt.load.string, wasm.func_list.__heap_alloc_string, wasm.func_list.__heap_alloc_vec, wasm.table_list.__indirect_function_table, util.invokeFunction, util.dropFunctionRef; + getPointer, createPointer, updatePointer, memory, storeU8, storeU32, storeFloat, loadU8, loadU32, loadFloat, loadString, allocString, allocVec, functions, invokeFunction, dropFunctionRef, wakeFuture = util.getPointer, util.createPointer, util.updatePointer, wasm.memory_list.memory, rt.store.i32_n8, rt.store.i32, rt.store.f64, rt.load.i32_u8, rt.load.i32, rt.load.f64, rt.load.string, wasm.func_list.__heap_alloc_string, wasm.func_list.__heap_alloc_vec, wasm.table_list.__indirect_function_table, util.invokeFunction, util.dropFunctionRef, wasm.func_list.rors_wake_future; end function abi.ffi.disconnect_connection(connection) local func = connections[connection]; @@ -145,12 +145,20 @@ function abi.ffi.method_instance_is_descendant_of(self, ancestor) return result_0 and 1 or 0; end function abi.ffi.method_instance_wait_for_child(self, child_name_addr, child_name_len, time_out) - local result_0 = getPointer(self):WaitForChild(loadString(memory, child_name_addr, child_name_len), time_out); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):WaitForChild(loadString(memory, child_name_addr, child_name_len), time_out); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_instance_ancestry_changed_on_ancestry_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AncestryChanged:Connect(function(child, parent) @@ -330,20 +338,36 @@ function abi.ffi.method_animation_clip_provider_register_animation_clip(self, an return createPointer(result_0); end function abi.ffi.method_animation_clip_provider_get_animation_clip_async(self, asset_id) - local result_0 = getPointer(self):GetAnimationClipAsync(getPointer(asset_id)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetAnimationClipAsync(getPointer(asset_id)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_animation_clip_provider_get_animations(self, user_id) - local result_0 = getPointer(self):GetAnimations(user_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetAnimations(user_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_animation_stream_track_is_playing(self) local result_0 = getPointer(self).IsPlaying; @@ -520,20 +544,42 @@ function abi.ffi.property_setter_asset_patch_settings_patch_id_set_patch_id(self getPointer(self).PatchId = loadString(memory, value_addr, value_len); end function abi.ffi.method_asset_service_create_place_async(self, place_name_addr, place_name_len, template_place_id, description_addr, description_len) - local result_0 = getPointer(self):CreatePlaceAsync(loadString(memory, place_name_addr, place_name_len), template_place_id, loadString(memory, description_addr, description_len)); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CreatePlaceAsync(loadString(memory, place_name_addr, place_name_len), template_place_id, loadString(memory, description_addr, description_len)); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_asset_service_create_place_in_player_inventory_async(self, player, place_name_addr, place_name_len, template_place_id, description_addr, description_len) - local result_0 = getPointer(self):CreatePlaceInPlayerInventoryAsync(getPointer(player), loadString(memory, place_name_addr, place_name_len), template_place_id, loadString(memory, description_addr, description_len)); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CreatePlaceInPlayerInventoryAsync(getPointer(player), loadString(memory, place_name_addr, place_name_len), template_place_id, loadString(memory, description_addr, description_len)); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_asset_service_get_game_places_async(self) - local result_0 = getPointer(self):GetGamePlacesAsync(); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetGamePlacesAsync(); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_asset_service_save_place_async(self) getPointer(self):SavePlaceAsync() @@ -698,40 +744,79 @@ function abi.ffi.method_avatar_editor_service_prompt_update_outfit(self, outfit_ getPointer(self):PromptUpdateOutfit(outfit_id, getPointer(updated_outfit), rig_type) end function abi.ffi.method_avatar_editor_service_check_apply_default_clothing(self, humanoid_description) - local result_0 = getPointer(self):CheckApplyDefaultClothing(getPointer(humanoid_description)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CheckApplyDefaultClothing(getPointer(humanoid_description)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_avatar_editor_service_conform_to_avatar_rules(self, humanoid_description) - local result_0 = getPointer(self):ConformToAvatarRules(getPointer(humanoid_description)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):ConformToAvatarRules(getPointer(humanoid_description)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_avatar_editor_service_get_favorite(self, item_id, item_type) - local result_0 = getPointer(self):GetFavorite(item_id, item_type); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetFavorite(item_id, item_type); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_avatar_editor_service_get_outfits(self, outfit_source, outfit_type) - local result_0 = getPointer(self):GetOutfits(outfit_source, outfit_type); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetOutfits(outfit_source, outfit_type); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_avatar_editor_service_search_catalog(self, search_parameters) - local result_0 = getPointer(self):SearchCatalog(getPointer(search_parameters)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):SearchCatalog(getPointer(search_parameters)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_avatar_editor_service_prompt_allow_inventory_read_access_completed_on_prompt_allow_inventory_read_access_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptAllowInventoryReadAccessCompleted:Connect(function(result) @@ -890,12 +975,26 @@ function abi.ffi.event_tool_unequipped_on_unequipped(self, callback_data, callba return createPointer(result_0); end function abi.ffi.method_badge_service_award_badge(self, user_id, badge_id) - local result_0 = getPointer(self):AwardBadge(user_id, badge_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):AwardBadge(user_id, badge_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_badge_service_user_has_badge_async(self, user_id, badge_id) - local result_0 = getPointer(self):UserHasBadgeAsync(user_id, badge_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):UserHasBadgeAsync(user_id, badge_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_player_gui_current_screen_orientation(self) local result_0 = getPointer(self).CurrentScreenOrientation; @@ -1710,30 +1809,60 @@ function abi.ffi.method_chat_chat(self, part_or_character, message_addr, message getPointer(self):Chat(getPointer(part_or_character), loadString(memory, message_addr, message_len), color) end function abi.ffi.method_chat_can_user_chat_async(self, user_id) - local result_0 = getPointer(self):CanUserChatAsync(user_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CanUserChatAsync(user_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_chat_can_users_chat_async(self, user_id_from, user_id_to) - local result_0 = getPointer(self):CanUsersChatAsync(user_id_from, user_id_to); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CanUsersChatAsync(user_id_from, user_id_to); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_chat_filter_string_async(self, string_to_filter_addr, string_to_filter_len, player_from, player_to) - local result_0 = getPointer(self):FilterStringAsync(loadString(memory, string_to_filter_addr, string_to_filter_len), getPointer(player_from), getPointer(player_to)); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):FilterStringAsync(loadString(memory, string_to_filter_addr, string_to_filter_len), getPointer(player_from), getPointer(player_to)); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_chat_filter_string_for_broadcast(self, string_to_filter_addr, string_to_filter_len, player_from) - local result_0 = getPointer(self):FilterStringForBroadcast(loadString(memory, string_to_filter_addr, string_to_filter_len), getPointer(player_from)); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):FilterStringForBroadcast(loadString(memory, string_to_filter_addr, string_to_filter_len), getPointer(player_from)); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_chat_chatted_on_chatted(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Chatted:Connect(function(part, message, color) @@ -2939,12 +3068,20 @@ function abi.ffi.method_context_action_service_unbind_all_actions(self) getPointer(self):UnbindAllActions() end function abi.ffi.method_context_action_service_get_button(self, action_name_addr, action_name_len) - local result_0 = getPointer(self):GetButton(loadString(memory, action_name_addr, action_name_len)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetButton(loadString(memory, action_name_addr, action_name_len)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_context_action_service_local_tool_equipped_on_local_tool_equipped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LocalToolEquipped:Connect(function(tool_equipped) @@ -3378,12 +3515,20 @@ function abi.ffi.method_data_store_service_get_request_budget_for_request_type(s return result_0; end function abi.ffi.method_data_store_service_list_data_stores_async(self, prefix_addr, prefix_len, page_size, cursor_addr, cursor_len) - local result_0 = getPointer(self):ListDataStoresAsync(loadString(memory, prefix_addr, prefix_len), page_size, loadString(memory, cursor_addr, cursor_len)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):ListDataStoresAsync(loadString(memory, prefix_addr, prefix_len), page_size, loadString(memory, cursor_addr, cursor_len)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_debris_add_item(self, item, lifetime) getPointer(self):AddItem(getPointer(item), lifetime) @@ -3930,39 +4075,71 @@ function abi.ffi.property_setter_get_text_bounds_params_width_set_width(self, va getPointer(self).Width = value; end function abi.ffi.method_data_store_list_keys_async(self, prefix_addr, prefix_len, page_size, cursor_addr, cursor_len) - local result_0 = getPointer(self):ListKeysAsync(loadString(memory, prefix_addr, prefix_len), page_size, loadString(memory, cursor_addr, cursor_len)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):ListKeysAsync(loadString(memory, prefix_addr, prefix_len), page_size, loadString(memory, cursor_addr, cursor_len)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_data_store_list_versions_async(self, key_addr, key_len, sort_direction, min_date, max_date, page_size) - local result_0 = getPointer(self):ListVersionsAsync(loadString(memory, key_addr, key_len), sort_direction, min_date, max_date, page_size); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):ListVersionsAsync(loadString(memory, key_addr, key_len), sort_direction, min_date, max_date, page_size); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_data_store_remove_version_async(self, key_addr, key_len, version_addr, version_len) getPointer(self):RemoveVersionAsync(loadString(memory, key_addr, key_len), loadString(memory, version_addr, version_len)) end function abi.ffi.method_group_service_get_allies_async(self, group_id) - local result_0 = getPointer(self):GetAlliesAsync(group_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetAlliesAsync(group_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_group_service_get_enemies_async(self, group_id) - local result_0 = getPointer(self):GetEnemiesAsync(group_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetEnemiesAsync(group_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_gui_base_2_d_absolute_position(self) local result_0 = getPointer(self).AbsolutePosition; @@ -6429,8 +6606,15 @@ function abi.ffi.method_humanoid_apply_description_reset(self, humanoid_descript getPointer(self):ApplyDescriptionReset(getPointer(humanoid_description), asset_type_verification) end function abi.ffi.method_humanoid_play_emote(self, emote_name_addr, emote_name_len) - local result_0 = getPointer(self):PlayEmote(loadString(memory, emote_name_addr, emote_name_len)); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):PlayEmote(loadString(memory, emote_name_addr, emote_name_len)); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_humanoid_climbing_on_climbing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Climbing:Connect(function(speed) @@ -7275,24 +7459,47 @@ function abi.ffi.method_input_object_is_modifier_key_down(self, modifier_key) return result_0 and 1 or 0; end function abi.ffi.method_insert_service_get_latest_asset_version_async(self, asset_id) - local result_0 = getPointer(self):GetLatestAssetVersionAsync(asset_id); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetLatestAssetVersionAsync(asset_id); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_insert_service_load_asset(self, asset_id) - local result_0 = getPointer(self):LoadAsset(asset_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):LoadAsset(asset_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_insert_service_load_asset_version(self, asset_version_id) - local result_0 = getPointer(self):LoadAssetVersion(asset_version_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):LoadAssetVersion(asset_version_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_joint_instance_active(self) local result_0 = getPointer(self).Active; @@ -7440,20 +7647,36 @@ function abi.ffi.method_keyframe_sequence_provider_register_keyframe_sequence(se return createPointer(result_0); end function abi.ffi.method_keyframe_sequence_provider_get_animations(self, user_id) - local result_0 = getPointer(self):GetAnimations(user_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetAnimations(user_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_keyframe_sequence_provider_get_keyframe_sequence_async(self, asset_id) - local result_0 = getPointer(self):GetKeyframeSequenceAsync(getPointer(asset_id)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetKeyframeSequenceAsync(getPointer(asset_id)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_light_brightness(self) local result_0 = getPointer(self).Brightness; @@ -7701,29 +7924,53 @@ function abi.ffi.method_localization_service_get_translator_for_player(self, pla return result_0_optional, result_0_optional_0; end function abi.ffi.method_localization_service_get_country_region_for_player_async(self, player) - local result_0 = getPointer(self):GetCountryRegionForPlayerAsync(getPointer(player)); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetCountryRegionForPlayerAsync(getPointer(player)); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_localization_service_get_translator_for_locale_async(self, locale_addr, locale_len) - local result_0 = getPointer(self):GetTranslatorForLocaleAsync(loadString(memory, locale_addr, locale_len)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetTranslatorForLocaleAsync(loadString(memory, locale_addr, locale_len)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_localization_service_get_translator_for_player_async(self, player) - local result_0 = getPointer(self):GetTranslatorForPlayerAsync(getPointer(player)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetTranslatorForPlayerAsync(getPointer(player)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_localization_table_source_locale_id(self) local result_0 = getPointer(self).SourceLocaleId; @@ -7845,28 +8092,64 @@ function abi.ffi.method_marketplace_service_prompt_subscription_purchase(self, p getPointer(self):PromptSubscriptionPurchase(getPointer(player), subscription_id) end function abi.ffi.method_marketplace_service_get_developer_products_async(self) - local result_0 = getPointer(self):GetDeveloperProductsAsync(); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetDeveloperProductsAsync(); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_marketplace_service_is_player_subscribed(self, player, subscription_id) - local result_0 = getPointer(self):IsPlayerSubscribed(getPointer(player), subscription_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):IsPlayerSubscribed(getPointer(player), subscription_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_marketplace_service_player_owns_asset(self, player, asset_id) - local result_0 = getPointer(self):PlayerOwnsAsset(getPointer(player), asset_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):PlayerOwnsAsset(getPointer(player), asset_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_marketplace_service_player_owns_bundle(self, player, bundle_id) - local result_0 = getPointer(self):PlayerOwnsBundle(getPointer(player), bundle_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):PlayerOwnsBundle(getPointer(player), bundle_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_marketplace_service_user_owns_game_pass_async(self, user_id, game_pass_id) - local result_0 = getPointer(self):UserOwnsGamePassAsync(user_id, game_pass_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):UserOwnsGamePassAsync(user_id, game_pass_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_marketplace_service_prompt_bundle_purchase_finished_on_prompt_bundle_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptBundlePurchaseFinished:Connect(function(player, bundle_id, was_purchased) @@ -9254,8 +9537,15 @@ function abi.ffi.property_getter_path_status(self) return result_0; end function abi.ffi.method_path_check_occlusion_async(self, start) - local result_0 = getPointer(self):CheckOcclusionAsync(start); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CheckOcclusionAsync(start); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_path_compute_async(self, start, finish) getPointer(self):ComputeAsync(getPointer(start), getPointer(finish)) @@ -9333,12 +9623,20 @@ function abi.ffi.property_setter_pathfinding_modifier_pass_through_set_pass_thro getPointer(self).PassThrough = value == 1; end function abi.ffi.method_pathfinding_service_find_path_async(self, start, finish) - local result_0 = getPointer(self):FindPathAsync(getPointer(start), getPointer(finish)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):FindPathAsync(getPointer(start), getPointer(finish)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_physics_service_collision_group_contains_part(self, name_addr, name_len, part) local result_0 = getPointer(self):CollisionGroupContainsPart(loadString(memory, name_addr, name_len), getPointer(part)); @@ -9624,25 +9922,54 @@ function abi.ffi.method_player_move(self, walk_direction, relative_to_camera) getPointer(self):Move(getPointer(walk_direction), relative_to_camera == 1) end function abi.ffi.method_player_get_rank_in_group(self, group_id) - local result_0 = getPointer(self):GetRankInGroup(group_id); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetRankInGroup(group_id); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_player_get_role_in_group(self, group_id) - local result_0 = getPointer(self):GetRoleInGroup(group_id); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetRoleInGroup(group_id); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_player_is_friends_with(self, user_id) - local result_0 = getPointer(self):IsFriendsWith(user_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):IsFriendsWith(user_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_player_is_in_group(self, group_id) - local result_0 = getPointer(self):IsInGroup(group_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):IsInGroup(group_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_player_load_character(self) getPointer(self):LoadCharacter() @@ -9794,57 +10121,112 @@ function abi.ffi.method_players_get_player_from_character(self, character) return result_0_optional, result_0_optional_0; end function abi.ffi.method_players_create_humanoid_model_from_description(self, description, rig_type, asset_type_verification) - local result_0 = getPointer(self):CreateHumanoidModelFromDescription(getPointer(description), rig_type, asset_type_verification); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CreateHumanoidModelFromDescription(getPointer(description), rig_type, asset_type_verification); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_create_humanoid_model_from_user_id(self, user_id) - local result_0 = getPointer(self):CreateHumanoidModelFromUserId(user_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CreateHumanoidModelFromUserId(user_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_get_friends_async(self, user_id) - local result_0 = getPointer(self):GetFriendsAsync(user_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetFriendsAsync(user_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_get_humanoid_description_from_outfit_id(self, outfit_id) - local result_0 = getPointer(self):GetHumanoidDescriptionFromOutfitId(outfit_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetHumanoidDescriptionFromOutfitId(outfit_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_get_humanoid_description_from_user_id(self, user_id) - local result_0 = getPointer(self):GetHumanoidDescriptionFromUserId(user_id); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetHumanoidDescriptionFromUserId(user_id); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_get_name_from_user_id_async(self, user_id) - local result_0 = getPointer(self):GetNameFromUserIdAsync(user_id); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetNameFromUserIdAsync(user_id); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_players_get_user_id_from_name_async(self, user_name_addr, user_name_len) - local result_0 = getPointer(self):GetUserIdFromNameAsync(loadString(memory, user_name_addr, user_name_len)); - return result_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetUserIdFromNameAsync(loadString(memory, user_name_addr, user_name_len)); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_players_player_added_on_player_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerAdded:Connect(function(player) @@ -10811,8 +11193,15 @@ function abi.ffi.method_social_service_prompt_game_invite(self, player) getPointer(self):PromptGameInvite(getPointer(player)) end function abi.ffi.method_social_service_can_send_game_invite_async(self, player, recipient_id) - local result_0 = getPointer(self):CanSendGameInviteAsync(getPointer(player), recipient_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):CanSendGameInviteAsync(getPointer(player), recipient_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_sound_is_loaded(self) local result_0 = getPointer(self).IsLoaded; @@ -11726,12 +12115,20 @@ function abi.ffi.method_text_channel_display_system_message(self, system_message return result_0_optional, result_0_optional_0; end function abi.ffi.method_text_channel_send_async(self, message_addr, message_len, metadata_addr, metadata_len) - local result_0 = getPointer(self):SendAsync(loadString(memory, message_addr, message_len), loadString(memory, metadata_addr, metadata_len)); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):SendAsync(loadString(memory, message_addr, message_len), loadString(memory, metadata_addr, metadata_len)); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.event_text_channel_message_received_on_message_received(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageReceived:Connect(function(incoming_message) @@ -12083,47 +12480,86 @@ function abi.ffi.event_text_chat_service_sending_message_on_sending_message(self return createPointer(result_0); end function abi.ffi.method_text_filter_result_get_chat_for_user_async(self, to_user_id) - local result_0 = getPointer(self):GetChatForUserAsync(to_user_id); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetChatForUserAsync(to_user_id); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_text_filter_result_get_non_chat_string_for_broadcast_async(self) - local result_0 = getPointer(self):GetNonChatStringForBroadcastAsync(); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetNonChatStringForBroadcastAsync(); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_text_filter_result_get_non_chat_string_for_user_async(self, to_user_id) - local result_0 = getPointer(self):GetNonChatStringForUserAsync(to_user_id); - local result_0_len = #result_0; - local result_0_content = allocString(result_0_len); - for i = 1, result_0_len do - storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); - end - return result_0_content, result_0_len; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetNonChatStringForUserAsync(to_user_id); + local result_0_len = #result_0; + local result_0_content = allocString(result_0_len); + for i = 1, result_0_len do + storeU8(memory, result_0_content + (i - 1), string.byte(result_0:sub(i, i))); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_content); + storeU32(memory, output_addr + 4, result_0_len); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_text_service_get_text_size(self, string_addr, string_len, font_size, font, frame_size) local result_0 = getPointer(self):GetTextSize(loadString(memory, string_addr, string_len), font_size, font, getPointer(frame_size)); return createPointer(result_0); end function abi.ffi.method_text_service_filter_string_async(self, string_to_filter_addr, string_to_filter_len, from_user_id, text_context) - local result_0 = getPointer(self):FilterStringAsync(loadString(memory, string_to_filter_addr, string_to_filter_len), from_user_id, text_context); - local result_0_optional, result_0_optional_0 = 0, 0; - if (result_0 ~= nil) then - result_0_optional, result_0_optional_0 = 1, createPointer(result_0); - end - return result_0_optional, result_0_optional_0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):FilterStringAsync(loadString(memory, string_to_filter_addr, string_to_filter_len), from_user_id, text_context); + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + local output_addr = allocVec(8); + storeU32(memory, output_addr + 0, result_0_optional); + storeU32(memory, output_addr + 4, result_0_optional_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_text_service_get_text_bounds_async(self, params) - local result_0 = getPointer(self):GetTextBoundsAsync(getPointer(params)); - return createPointer(result_0); + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):GetTextBoundsAsync(getPointer(params)); + local output_addr = allocVec(4); + storeU32(memory, output_addr + 0, createPointer(result_0)); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_text_source_can_send(self) local result_0 = getPointer(self).CanSend; @@ -13401,12 +13837,26 @@ function abi.ffi.method_vector_3_curve_z(self) return result_0_optional, result_0_optional_0; end function abi.ffi.method_voice_chat_internal_is_voice_enabled_for_user_id_async(self, user_id) - local result_0 = getPointer(self):IsVoiceEnabledForUserIdAsync(user_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):IsVoiceEnabledForUserIdAsync(user_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.method_voice_chat_service_is_voice_enabled_for_user_id_async(self, user_id) - local result_0 = getPointer(self):IsVoiceEnabledForUserIdAsync(user_id); - return result_0 and 1 or 0; + local future = createPointer(0); + task.spawn(function() + local result_0 = getPointer(self):IsVoiceEnabledForUserIdAsync(user_id); + local output_addr = allocVec(4); + storeU8(memory, output_addr + 0, result_0 and 1 or 0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; end function abi.ffi.property_getter_voice_source_user_id(self) local result_0 = getPointer(self).UserId; diff --git a/roblox/init.server.luau b/roblox/init.server.luau index db1dedd..f6abbd5 100644 --- a/roblox/init.server.luau +++ b/roblox/init.server.luau @@ -1,19 +1,74 @@ local rt = require(script.runtime); local wasm, memory, util; -local createPointer, getPointer, dropPointer, invokeOnce, readString, writeStringReturn; +local createPointer, getPointer, dropPointer, updatePointer, invokeOnce, readString, writeStringReturn; -local function wrapConstructorNumber(constructor) - return function(...) - return createPointer(constructor(...)); - end +-- TODO: dropped futures are unsafe +local function createFuture(store, func, ...) + local future = createPointer(0); + + task.spawn(function(...) + updatePointer(future, store(func(...))); + wasm.func_list.rors_wake_future(future); + end, ...); + + return future; end -local function wrapConstructorString(constructor) - return function(addr, len) - return createPointer(constructor(addr, len)); +local function createAsyncRuntime() + -- context, futures and tasks could be represented as a single pointer (Box) for simplicity + local queue = {}; + + local function createContext(awakener) + return wasm.function_list.create_context(createPointer(awakener)); + end + + local function awaken(context) + getPointer(context)(); + end + + local function pollFuture(future, context) + return wasm.function_list.poll_future(future, context); end + + local function runTask(task) + table.insert(queue, task); + end + + local function waitOn(task) + local thread = coroutine.running(); + local awake = false; + local context = createContext(function() + awake = true; + coroutine.resume(thread); + end); + + local data; + while true do + data = table.pack(pollFuture(task, context)); + + -- Check for Poll::Ready + if (data[1] == 1) then + break; + end + + -- If the task immediately awakens, don't yield + if (awake) then + awake = false; + continue; + end + + coroutine.yield(); + end + + dropPointer(context); + return table.unpack(data, 2, data.n); + end + + return { runTask = runTask, waitOn = waitOn, awaken = awaken }; end +local runtime = createAsyncRuntime(); + local env = { -- lbiraries lib_task_delay = function(delay, stack, fn_ptr) @@ -29,7 +84,19 @@ local env = { end, lib_task_wait = function(delay) - task.wait(delay); + return createFuture( + function(value) + local addr = wasm.func_list.__heap_alloc_vec(2); + rt.store.f64(memory, addr, value); + return addr; + end, + task.wait, + delay + ); + end, + + get_poll_state = function(future) + return getPointer(future); end, -- pointers @@ -72,8 +139,8 @@ util = require(script.util)(rt, wasm, memory); abi.load(wasm, rt, util); -createPointer, getPointer, dropPointer, invokeOnce, readString = - util.createPointer, util.getPointer, util.dropPointer, util.invokeOnce, util.readString; +createPointer, getPointer, dropPointer, updatePointer, invokeOnce, readString = + util.createPointer, util.getPointer, util.dropPointer, util.updatePointer, util.invokeOnce, util.readString; task.wait(2); print("start wasm"); diff --git a/roblox/util.luau b/roblox/util.luau index cb131c8..adbbbd9 100644 --- a/roblox/util.luau +++ b/roblox/util.luau @@ -18,6 +18,10 @@ return function(rt, wasm, memory) return pointers[id]; end + local function updatePointer(id, value) + pointers[id] = value; + end + local function dropPointer(id) pointers[id] = pointers.last; pointers.last = id; @@ -48,14 +52,6 @@ return function(rt, wasm, memory) return invokeFunction(data, vtable, ...); end - local function allocString(text) - local vec = wasm.func_list.__heap_alloc_string(#text); - for i = 1, #text do - rt.store.i32_n8(memory, vec + i - 1, string.byte(text, i, i)); - end - return vec; - end - local function readString(addr, len) local s = ""; for i = 1, len do @@ -65,10 +61,10 @@ return function(rt, wasm, memory) end return { - writeStringReturn = writeStringReturn, dropFunctionRef = dropFunctionRef, invokeFunction = invokeFunction, createPointer = createPointer, + updatePointer = updatePointer, dropPointer = dropPointer, readString = readString, getPointer = getPointer, diff --git a/src/futures/ffi.rs b/src/futures/ffi.rs new file mode 100644 index 0000000..1ed4066 --- /dev/null +++ b/src/futures/ffi.rs @@ -0,0 +1,88 @@ +// Rust future on Lua side +// pub struct RustFuture {} + +use std::{ + cell::RefCell, + future::Future, + marker::PhantomData, + pin::Pin, + task::{Context, Poll, Waker}, +}; + +use crate::drop_pointer; + +#[cfg(not(feature = "multivalue"))] +use collections::HashMap; + +extern "C" { + // Returns the heap allocated value, if any + fn get_poll_state(future: u32) -> *mut (); +} + +#[no_mangle] +fn rors_wake_future(future: u32) { + #[cfg(not(feature = "multivalue"))] + WAKERS.with(|v| { + let mut wakers = v.borrow_mut(); + if let Some(waker) = wakers.get(&future) { + waker.wake_by_ref(); + wakers.remove(&future); + } + }); + + #[cfg(feature = "multivalue")] + WAKERS.with(|v| { + let mut wakers = v.borrow_mut(); + wakers.retain(|(i, waker)| { + if *i == future { + waker.wake_by_ref(); + false + } else { + true + } + }); + }); +} + +#[cfg(not(feature = "multivalue"))] +thread_local! { + static WAKERS: RefCell> = RefCell::new(HashMap::new()); +} + +#[cfg(feature = "multivalue")] +thread_local! { + static WAKERS: RefCell> = RefCell::new(Vec::new()); +} + +/// Yielding lua code future +#[repr(transparent)] +#[must_use = "futures do nothing unless polled"] +pub struct LuaFuture(u32, PhantomData); + +impl Future for LuaFuture { + type Output = O; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.0 == 0 { + panic!("attempt to poll dead future"); + } + + unsafe { + let ptr = get_poll_state(self.0) as *mut O; + if !ptr.is_null() { + drop_pointer(self.0); + self.get_unchecked_mut().0 = 0; + + Poll::Ready(*Box::from_raw(ptr)) + } else { + #[cfg(not(feature = "multivalue"))] + WAKERS.with(|v| v.borrow_mut().insert(self.0, cx.waker().clone())); + + #[cfg(feature = "multivalue")] + WAKERS.with(|v| v.borrow_mut().push((self.0, cx.waker().clone()))); + + Poll::Pending + } + } + } +} diff --git a/src/futures/mod.rs b/src/futures/mod.rs new file mode 100644 index 0000000..e6d53a1 --- /dev/null +++ b/src/futures/mod.rs @@ -0,0 +1,11 @@ +pub mod ffi; +mod task; +mod waker; + +use std::future::Future; + +use self::task::Task; + +pub fn spawn + 'static>(future: F) { + Task::new(Box::pin(future)).execute(); +} diff --git a/src/futures/task.rs b/src/futures/task.rs new file mode 100644 index 0000000..27eb071 --- /dev/null +++ b/src/futures/task.rs @@ -0,0 +1,61 @@ +use std::{ + cell::{Cell, RefCell}, + future::Future, + pin::Pin, + rc::Rc, + task::{Context, RawWaker, Waker}, +}; + +use super::waker::WAKER_VTABLE; + +pub struct TaskFuture { + future: Pin + 'static>>, + waker: Waker, +} + +pub struct Task { + future: RefCell>, + queued: Cell, +} + +impl Task { + pub fn new(future: Pin + 'static>>) -> Rc { + let task = Rc::new(Task { + future: RefCell::new(None), + queued: Cell::new(false), + }); + + let waker = unsafe { Waker::from_raw(task.clone().raw_waker()) }; + + task.future.replace(Some(TaskFuture { future, waker })); + task + } + + pub fn wake_by_ref(self: &Rc) { + if !self.queued.replace(true) { + let task = self.clone(); + crate::task::defer(move || task.execute()); + } + } + + pub fn raw_waker(self: Rc) -> RawWaker { + RawWaker::new(Rc::into_raw(self) as *const (), &WAKER_VTABLE) + } + + pub fn execute(&self) { + self.queued.replace(false); + + let mut task_future = self.future.borrow_mut(); + let future = match task_future.as_mut() { + Some(future) => future, + None => return, + }; + + let mut context = Context::from_waker(&future.waker); + let status = future.future.as_mut().poll(&mut context); + + if status.is_ready() { + self.future.replace(None); + } + } +} diff --git a/src/futures/waker.rs b/src/futures/waker.rs new file mode 100644 index 0000000..e4c7a7c --- /dev/null +++ b/src/futures/waker.rs @@ -0,0 +1,31 @@ +use std::{ + mem::forget, + rc::Rc, + task::{RawWaker, RawWakerVTable}, +}; + +use super::task::Task; + +unsafe fn clone(ptr: *const ()) -> RawWaker { + let ptr = Rc::from_raw(ptr as *const Task); + let raw_waker = ptr.clone().raw_waker(); + forget(ptr); + raw_waker +} + +unsafe fn wake(ptr: *const ()) { + let ptr = Rc::from_raw(ptr as *const Task); + ptr.wake_by_ref(); +} + +unsafe fn wake_by_ref(ptr: *const ()) { + let ptr = Rc::from_raw(ptr as *const Task); + ptr.wake_by_ref(); + forget(ptr); +} + +unsafe fn drop(ptr: *const ()) { + Rc::from_raw(ptr as *const Task); +} + +pub(super) const WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); diff --git a/src/lib.rs b/src/lib.rs index 0b6733c..ba024ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,8 @@ +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] + pub mod datatypes; +pub mod futures; pub mod generated; pub mod libraries; pub mod mem; diff --git a/src/libraries/task.rs b/src/libraries/task.rs index 898f867..a1ce0bb 100644 --- a/src/libraries/task.rs +++ b/src/libraries/task.rs @@ -1,9 +1,11 @@ +use crate::futures::ffi::LuaFuture; + #[allow(improper_ctypes)] extern "C" { fn lib_task_delay(amount: f64, task: Box); fn lib_task_defer(task: Box); fn lib_task_spawn(task: Box); - fn lib_task_wait(amount: f64) -> f64; + fn lib_task_wait(amount: f64) -> LuaFuture; } pub fn delay(amount: f64, value: F) { @@ -18,8 +20,6 @@ pub fn spawn(value: F) { unsafe { lib_task_spawn(Box::new(value)) } } -/// This should not be used until async/await is supported as yielding in Rust code is UB. -#[deprecated] -pub fn wait(amount: f64) -> f64 { +pub fn wait(amount: f64) -> LuaFuture { unsafe { lib_task_wait(amount) } } From 6a6be1cec6220dbf51d286193b064f61eb3f86ad Mon Sep 17 00:00:00 2001 From: fireboltofdeath <24422634+Fireboltofdeath@users.noreply.github.com> Date: Tue, 3 Jan 2023 19:17:49 -0500 Subject: [PATCH 2/5] wip --- build/codegen/luau/conversion.rs | 4 +- build/codegen/rust/constants.rs | 8 ++ build/codegen/rust/conversion.rs | 76 +++++++++++++----- build/codegen/rust/mod.rs | 29 +++++-- build/codegen/structs/layout.rs | 13 +++- build/codegen/structs/types.rs | 11 ++- build/dump/mod.rs | 5 +- build/overrides.rs | 10 ++- examples/test.rs | 6 +- roblox/abi.luau | 4 +- src/conversion/impls.rs | 58 ++++++++++++++ src/conversion/mod.rs | 33 ++++++++ src/conversion/structs.rs | 21 +++++ src/futures/ffi.rs | 130 ++++++++++++++++++++++++++++++- src/futures/task.rs | 51 +++++++++++- src/futures/waker.rs | 57 ++++++++------ src/generated.rs | 5 ++ src/lib.rs | 1 + src/libraries/standard.rs | 2 +- 19 files changed, 452 insertions(+), 72 deletions(-) create mode 100644 src/conversion/impls.rs create mode 100644 src/conversion/mod.rs create mode 100644 src/conversion/structs.rs diff --git a/build/codegen/luau/conversion.rs b/build/codegen/luau/conversion.rs index 4c6b8a0..544813e 100644 --- a/build/codegen/luau/conversion.rs +++ b/build/codegen/luau/conversion.rs @@ -42,7 +42,7 @@ pub fn convert_luau_to_rust( variadic: bool, ) -> Vec { match &kind { - CodegenKind::Function(_, _) => panic!(), + CodegenKind::Function(_, _, _) => panic!(), CodegenKind::Optional(kind) => { let param_optional = ids.next_names(&[identifier, "optional"]); let width = kind.width(); @@ -138,7 +138,7 @@ pub fn convert_rust_to_luau( prereqs: &mut Vec, ) -> String { match ¶meter.kind { - CodegenKind::Function(parameters, output) => { + CodegenKind::Function(parameters, output, _) => { let layout = output.layout(); let parameter_names: Vec<_> = parameters.iter().map(get_lua_parameter_name).collect(); diff --git a/build/codegen/rust/constants.rs b/build/codegen/rust/constants.rs index 8258196..6f34580 100644 --- a/build/codegen/rust/constants.rs +++ b/build/codegen/rust/constants.rs @@ -26,6 +26,14 @@ impl From> for Vec { } "; +pub const RUST_CLOSURE: &str = "\ +#[repr(C)] +pub struct RustClosure { + closure: F, + poll: unsafe extern \"C\" fn(id: u32) -> TaskResult, +} +"; + pub const RUST_OPTION: &str = "\ #[repr(C)] pub enum RustOption { diff --git a/build/codegen/rust/conversion.rs b/build/codegen/rust/conversion.rs index 13fbaab..f65b964 100644 --- a/build/codegen/rust/conversion.rs +++ b/build/codegen/rust/conversion.rs @@ -1,6 +1,6 @@ use crate::codegen::{ stream::{note, pull, push, Stream}, - structs::CodegenKind, + structs::{Async, CodegenKind}, }; use super::raw_name; @@ -8,7 +8,7 @@ use super::raw_name; // The bindings pass these types to the Luau bindings pub fn get_borrowed_ffi_type(kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(inputs, result) => { + CodegenKind::Function(inputs, result, is_async) => { let return_type = get_owned_ffi_type(result); let parameters = inputs .iter() @@ -16,7 +16,11 @@ pub fn get_borrowed_ffi_type(kind: &CodegenKind) -> String { .collect::>() .join(", "); - format!("Box {return_type}>") + if matches!(is_async, Async::Yes) { + format!("RustClosure RustFuture>, {return_type}>") + } else { + format!("Box {return_type}>") + } } CodegenKind::Optional(kind) => format!("RustOption<{}>", get_borrowed_ffi_type(kind)), CodegenKind::Tuple(kind) => format!("RustSlice<{}>", get_borrowed_ffi_type(kind)), @@ -35,7 +39,7 @@ pub fn get_borrowed_ffi_type(kind: &CodegenKind) -> String { // The bindings receive these types from the Lua bindings pub fn get_owned_ffi_type(kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(_, _) => unimplemented!(), + CodegenKind::Function(_, _, _) => unimplemented!(), CodegenKind::Optional(kind) => format!("RustOption<{}>", get_owned_ffi_type(kind)), CodegenKind::Tuple(kind) => format!("RustVec<{}>", get_owned_ffi_type(kind)), CodegenKind::Vec(kind) => format!("RustVec<{}>", get_owned_ffi_type(kind)), @@ -53,7 +57,7 @@ pub fn get_owned_ffi_type(kind: &CodegenKind) -> String { // Users pass these types to the Rust bindings pub fn get_borrowed_rust_type(kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(inputs, result) => { + CodegenKind::Function(inputs, result, is_async) => { let return_type = get_owned_rust_type(result); let parameters = inputs .iter() @@ -61,7 +65,11 @@ pub fn get_borrowed_rust_type(kind: &CodegenKind) -> String { .collect::>() .join(", "); - format!("impl FnMut({parameters}) -> {return_type} + 'static") + if matches!(is_async, Async::Yes) { + format!("impl Fn({parameters}) -> Fut + 'static") + } else { + format!("impl FnMut({parameters}) -> {return_type} + 'static") + } } CodegenKind::Optional(kind) => format!("&Option<{}>", get_borrowed_rust_type(kind)), CodegenKind::Tuple(kind) => format!("&[{}]", get_borrowed_rust_type(kind)), @@ -80,7 +88,7 @@ pub fn get_borrowed_rust_type(kind: &CodegenKind) -> String { // Users receive these types from the Rust bindings pub fn get_owned_rust_type(kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(_, _) => unimplemented!(), + CodegenKind::Function(_, _, _) => unimplemented!(), CodegenKind::Optional(kind) => format!("Option<{}>", get_owned_rust_type(kind)), CodegenKind::Tuple(kind) => format!("Vec<{}>", get_owned_rust_type(kind)), CodegenKind::Vec(kind) => format!("Vec<{}>", get_owned_rust_type(kind)), @@ -97,8 +105,9 @@ pub fn get_owned_rust_type(kind: &CodegenKind) -> String { pub fn borrowed_rust_to_ffi(expression: &str, kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(inputs, output) => { - if inputs.is_empty() && matches!(output.as_ref(), CodegenKind::Void) { + CodegenKind::Function(inputs, output, is_async) => { + let is_async = matches!(is_async, Async::Yes); + if inputs.is_empty() && matches!(output.as_ref(), CodegenKind::Void) && !is_async { return format!("Box::new({expression})"); } @@ -108,22 +117,53 @@ pub fn borrowed_rust_to_ffi(expression: &str, kind: &CodegenKind) -> String { .map(|v| owned_ffi_to_rust(&raw_name(&v.name), &v.kind)) .collect(); - Stream::expression(|stream| { + let closure = Stream::expression(|stream| { let input_names = input_names.join(", "); let transformed_inputs = transformed_inputs.join(", "); let has_return = !matches!(output.as_ref(), CodegenKind::Void); - let expression = format!("{expression}({transformed_inputs})"); + let conversion = if is_async { + format!("callback({transformed_inputs}).await") + } else { + format!("{expression}({transformed_inputs})") + }; + + if is_async { + push!(stream, "{{"); + note!(stream, "let callback = Rc::new({expression});"); + push!(stream, "Box::new(move |{input_names}| {{"); + note!(stream, "let callback = callback.clone();"); + push!(stream, "RustFuture::new(Box::new(async move {{"); + } else { + push!(stream, "Box::new(move |{input_names}| {{"); + } - push!(stream, "Box::new(move |{input_names}| {{"); if has_return { - let transformation = owned_rust_to_ffi(&expression, output); + let transformation = owned_rust_to_ffi(&conversion, output); note!(stream, "{transformation}"); } else { - note!(stream, "{expression}"); + note!(stream, "{conversion}"); } - pull!(stream, "}})"); - }) + + if is_async { + pull!(stream, "}}))"); + pull!(stream, "}})"); + pull!(stream, "}}"); + } else { + pull!(stream, "}})"); + } + }); + + if is_async { + Stream::expression(|stream| { + push!(stream, "RustClosure {{"); + note!(stream, "closure: {closure},"); + note!(stream, "poll: RustFuture::poll_future,"); + pull!(stream, "}}"); + }) + } else { + closure + } } CodegenKind::Optional(kind) => { let conversion = borrowed_rust_to_ffi("value", kind); @@ -154,7 +194,7 @@ pub fn borrowed_rust_to_ffi(expression: &str, kind: &CodegenKind) -> String { pub fn owned_ffi_to_rust(expression: &str, kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(_, _) => unreachable!(), + CodegenKind::Function(_, _, _) => unreachable!(), CodegenKind::Optional(kind) => { let conversion = owned_ffi_to_rust("value", kind); let conversion_type = get_owned_ffi_type(kind); @@ -183,7 +223,7 @@ pub fn owned_ffi_to_rust(expression: &str, kind: &CodegenKind) -> String { pub fn owned_rust_to_ffi(expression: &str, kind: &CodegenKind) -> String { match kind { - CodegenKind::Function(_, _) => unimplemented!(), + CodegenKind::Function(_, _, _) => unimplemented!(), CodegenKind::Tuple(kind) => { let transformation = borrowed_rust_to_ffi("value", kind); diff --git a/build/codegen/rust/mod.rs b/build/codegen/rust/mod.rs index f284d38..e9471fe 100644 --- a/build/codegen/rust/mod.rs +++ b/build/codegen/rust/mod.rs @@ -2,14 +2,15 @@ use crate::{ codegen::{ rust::conversion::owned_ffi_to_rust, stream::{note, pull, write_to}, + structs::Async, }, dump::types::Enum, }; use self::{ constants::{ - EXCLUSIVE_INSTANCE, ROBLOX_CREATABLE, RUST_OPTION, RUST_ROBLOX_ENUM_MACRO, RUST_SLICE, - RUST_STRING, RUST_VEC, + EXCLUSIVE_INSTANCE, ROBLOX_CREATABLE, RUST_CLOSURE, RUST_OPTION, RUST_ROBLOX_ENUM_MACRO, + RUST_SLICE, RUST_STRING, RUST_VEC, }, conversion::{ borrowed_rust_to_ffi, get_borrowed_ffi_type, get_borrowed_rust_type, get_owned_ffi_type, @@ -101,10 +102,13 @@ fn generate_member_declaration(member: &Member, name: &str, context: Declaration let parameter_type = get_borrowed_type(kind); if name == "self" { parameters.push("&self".to_string()); - } else if let CodegenKind::Function(inputs, output) = &kind { + } else if let CodegenKind::Function(inputs, output, is_async) = &kind { let is_definition = matches!(context, DeclarationContext::Trait) || is_extern; - if inputs.is_empty() && matches!(output.as_ref(), CodegenKind::Void) || is_definition { + if inputs.is_empty() && matches!(output.as_ref(), CodegenKind::Void) + || is_definition + || matches!(is_async, Async::Yes) + { parameters.push(format!("{name}: {parameter_type}")) } else { parameters.push(format!("mut {name}: {parameter_type}")); @@ -126,7 +130,19 @@ fn generate_member_declaration(member: &Member, name: &str, context: Declaration write_to!(stream, "async "); } - write_to!(stream, "fn {name}({parameters})"); + write_to!(stream, "fn {name}"); + + // TODO: support multiple async closures? + if !is_extern { + for input in &member.inputs { + if let CodegenKind::Function(_, result, Async::Yes) = &input.kind { + let return_type = get_owned_rust_type(result); + write_to!(stream, ">") + } + } + } + + write_to!(stream, "({parameters})"); if is_async && is_extern { if outputs.len() > 1 { @@ -231,6 +247,7 @@ fn generate_constant(output: &mut Vec) { ROBLOX_CREATABLE, RUST_ROBLOX_ENUM_MACRO, EXCLUSIVE_INSTANCE, + RUST_CLOSURE, ] .map(ToString::to_string), ); @@ -239,8 +256,6 @@ fn generate_constant(output: &mut Vec) { pub fn generate(namespaces: &[Namespace], enums: &[Enum]) -> String { let mut output = Vec::new(); output.push(generate_extern(namespaces)); - output.push("use super::*;".to_string()); - output.push("use crate::futures::ffi::LuaFuture;".to_string()); generate_constant(&mut output); generate_enums(&mut output, enums); diff --git a/build/codegen/structs/layout.rs b/build/codegen/structs/layout.rs index 121f6f0..38e76a0 100644 --- a/build/codegen/structs/layout.rs +++ b/build/codegen/structs/layout.rs @@ -1,6 +1,6 @@ use crate::config::MULTI_VALUE_SUPPORT; -use super::CodegenKind; +use super::{Async, CodegenKind}; pub enum Representation { /// u32 / usize @@ -25,7 +25,16 @@ impl TypeLayout { representations.extend(TypeLayout::represent(kind)); representations } - CodegenKind::Function(_, _) => vec![Representation::Pointer, Representation::Pointer], + CodegenKind::Function(_, _, Async::Yes) => { + vec![ + Representation::Pointer, + Representation::Pointer, + Representation::Pointer, + ] + } + CodegenKind::Function(_, _, Async::No) => { + vec![Representation::Pointer, Representation::Pointer] + } CodegenKind::Instance(_) => vec![Representation::Pointer], CodegenKind::DataType(_) => vec![Representation::Pointer], CodegenKind::Tuple(_) => vec![Representation::Pointer, Representation::Pointer], diff --git a/build/codegen/structs/types.rs b/build/codegen/structs/types.rs index aaba070..f1da0f7 100644 --- a/build/codegen/structs/types.rs +++ b/build/codegen/structs/types.rs @@ -1,8 +1,14 @@ use super::{Parameter, TypeLayout}; +#[derive(Clone, Debug)] +pub enum Async { + Yes, + No, +} + #[derive(Clone, Debug)] pub enum CodegenKind { - Function(Vec, Box), + Function(Vec, Box, Async), Optional(Box), Tuple(Box), Vec(Box), @@ -24,9 +30,10 @@ impl CodegenKind { 1 => Some("len".to_string()), _ => unreachable!(), }, - CodegenKind::Function(_, _) => match index { + CodegenKind::Function(_, _, _) => match index { 0 => Some("data".to_string()), 1 => Some("vtable".to_string()), + 2 => Some("poll".to_string()), _ => unreachable!(), }, CodegenKind::Optional(kind) => match index { diff --git a/build/dump/mod.rs b/build/dump/mod.rs index 572f8fd..f29747c 100644 --- a/build/dump/mod.rs +++ b/build/dump/mod.rs @@ -8,7 +8,7 @@ use types::{ use crate::{ codegen::structs::{ - implementations, CodegenKind, InstanceMetadata, Member, MemberFlags, Namespace, + implementations, Async, CodegenKind, InstanceMetadata, Member, MemberFlags, Namespace, NamespaceKind, Parameter, }, config::{CLASS_BLACKLIST, DEPRECATED_APIS}, @@ -272,7 +272,7 @@ fn transform_class_event(dump: &Dump, event: &ClassEventMember) -> Option Opti CodegenKind::Function( inputs, Box::new(transform_value_type(&callback.return_type, false)), + Async::Yes, ), ), ], diff --git a/build/overrides.rs b/build/overrides.rs index 6d5463a..60cd080 100644 --- a/build/overrides.rs +++ b/build/overrides.rs @@ -1,6 +1,8 @@ use convert_case::{Case, Casing}; -use crate::codegen::structs::{implementations::*, CodegenKind, Member, MemberFlags, Parameter}; +use crate::codegen::structs::{ + implementations::*, Async, CodegenKind, Member, MemberFlags, Parameter, +}; pub struct PartialNamespace { /// Name of this namespace @@ -276,7 +278,8 @@ macro_rules! parse_namespace_fields { self: $kind, callback: CodegenKind::Function( vec![$(Parameter::new(stringify!($parameter), $type.clone())),*], - Box::new(CodegenKind::Void) + Box::new(CodegenKind::Void), + Async::No ) ) -> (datatype!(RbxScriptConnection)); }); @@ -296,7 +299,8 @@ macro_rules! parse_namespace_fields { self: $kind, callback: CodegenKind::Function( vec![$(Parameter::new(stringify!($parameter), $type.clone())),*], - Box::new($result.clone()) + Box::new($result.clone()), + Async::Yes ) ) -> (); }); diff --git a/examples/test.rs b/examples/test.rs index ba5707c..de2cc87 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use roblox_rs::{println, *}; // Use `wee_alloc` as the global allocator. -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +// #[global_allocator] +// static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; /// # Safety #[allow(unreachable_code)] @@ -82,7 +82,7 @@ pub fn main() { my_func.set_name("GOD FUNC"); my_func.set_parent(&Some(&Workspace::instance())); - my_func.on_server_invoke(move |player, values| { + my_func.on_server_invoke(move |player, values| async move { println!( "Wow, {} sent me messages that I will respond to:", player.name() diff --git a/roblox/abi.luau b/roblox/abi.luau index 6d17238..d901ced 100644 --- a/roblox/abi.luau +++ b/roblox/abi.luau @@ -10714,7 +10714,7 @@ function abi.ffi.method_remote_event_fire_server(self, values_addr, values_len) end getPointer(self):FireServer(unpack(values_vec, 1, values_len)) end -function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, callback_vtable) +function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, callback_vtable, callback_poll) getPointer(self).OnServerInvoke = function(player, ...) local values_tuple = { ... }; local values_len = select("#", ...); @@ -10732,7 +10732,7 @@ function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, return unpack(callback_vec, 1, result_1); end; end -function abi.ffi.callback_remote_function_on_client_invoke(self, callback_data, callback_vtable) +function abi.ffi.callback_remote_function_on_client_invoke(self, callback_data, callback_vtable, callback_poll) getPointer(self).OnClientInvoke = function(...) local values_tuple = { ... }; local values_len = select("#", ...); diff --git a/src/conversion/impls.rs b/src/conversion/impls.rs new file mode 100644 index 0000000..cbc8726 --- /dev/null +++ b/src/conversion/impls.rs @@ -0,0 +1,58 @@ +use super::{ + foreign, + structs::{RustOption, RustSlice, RustString}, + Foreign, FromForeign, IntoForeign, +}; + +impl IntoForeign for Option { + type Output = RustOption; + + fn into_foreign(self) -> Self::Output { + match self { + Some(value) => RustOption::Some(value.into_foreign()), + None => RustOption::None, + } + } +} + +impl FromForeign for Option { + type Input = RustOption; + + fn from_foreign(value: Self::Input) -> Self { + match value { + RustOption::Some(value) => Some(T::from_foreign(value)), + RustOption::None => None, + } + } +} + +impl FromForeign for String { + type Input = RustString; + + fn from_foreign(input: Self::Input) -> Self { + unsafe { String::from_raw_parts(input.content, input.length, input.length) } + } +} + +impl IntoForeign for &[T] { + type Output = RustSlice; + + fn into_foreign(self) -> Self::Output { + RustSlice { + content: self.as_ptr(), + length: self.len(), + } + } +} + +impl FromForeign for Vec { + type Input = RustSlice; + + fn from_foreign(input: Self::Input) -> Self {} +} + +// impl IntoForeign for &[T] { +// type Output = RustSlice; +// } + +foreign!(i8 u8 i16 u16 i32 u32 f32 i64 u64 f64 RustString RustSlice RustOption); diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs new file mode 100644 index 0000000..8a1202c --- /dev/null +++ b/src/conversion/mod.rs @@ -0,0 +1,33 @@ +mod impls; +mod structs; + +/// This is a marker trait for generic bounds that statically ensures only FFI safe types can be used +pub trait Foreign {} + +/// This trait is for converting to an FFI safe type. +pub trait IntoForeign { + type Output: Foreign; + + fn into_foreign(self) -> Self::Output; +} + +/// This trait is for converting from an FFI safe type. +pub trait FromForeign { + type Input: Foreign; + + fn from_foreign(input: Self::Input) -> Self; +} + +macro_rules! foreign { + ($name:ident<$($ty:ident),*> $($tt:tt)*) => { + impl<$($ty: $crate::conversion::Foreign),*> $crate::conversion::Foreign for $name<$($ty),*> {} + foreign!($($tt)*); + }; + ($name:ident $($tt:tt)*) => { + impl $crate::conversion::Foreign for $name {} + foreign!($($tt)*); + }; + () => {}; +} + +use foreign; diff --git a/src/conversion/structs.rs b/src/conversion/structs.rs new file mode 100644 index 0000000..c302ac2 --- /dev/null +++ b/src/conversion/structs.rs @@ -0,0 +1,21 @@ +use super::Foreign; + +#[repr(C)] +pub enum RustOption { + None, + Some(T), +} + +/// A FFI-safe string received from bindings. +/// Capacity is guaranteed to be equal to length as Luau never resizes strings. +#[repr(C)] +pub struct RustString { + pub content: *mut u8, + pub length: usize, +} + +#[repr(C)] +pub struct RustSlice { + pub content: *const T, + pub length: usize, +} diff --git a/src/futures/ffi.rs b/src/futures/ffi.rs index 1ed4066..f7410ea 100644 --- a/src/futures/ffi.rs +++ b/src/futures/ffi.rs @@ -6,13 +6,16 @@ use std::{ future::Future, marker::PhantomData, pin::Pin, - task::{Context, Poll, Waker}, + rc::Rc, + task::{Context, Poll, RawWaker, Waker}, }; use crate::drop_pointer; #[cfg(not(feature = "multivalue"))] -use collections::HashMap; +use std::collections::HashMap; + +use super::waker::lua_task_waker; extern "C" { // Returns the heap allocated value, if any @@ -86,3 +89,126 @@ impl Future for LuaFuture { } } } + +extern "C" { + fn wake_task(task_id: u32); + fn new_task() -> u32; +} + +thread_local! { + static TASKS: RefCell>> = RefCell::new(Vec::new()); +} + +#[repr(C)] +pub enum TaskResult { + None, + Ready(T), +} + +pub struct RustFutureTask { + task_id: u32, + waker: RefCell>, + future: *mut dyn Future, +} + +impl RustFutureTask { + pub fn raw_waker(self: Rc) -> RawWaker { + RawWaker::new(Rc::into_raw(self) as *const (), &lua_task_waker::WAKER) + } + + pub fn wake_by_ref(&self) { + let task_id = self.task_id; + unsafe { crate::task::defer(move || wake_task(task_id)) } + } +} + +#[repr(C)] +pub struct AsyncStatus(RustFuture, unsafe extern "C" fn(id: u32) -> TaskResult); + +pub fn black_box(dummy: T) -> T { + unsafe { + let ret = std::ptr::read_volatile(&dummy); + std::mem::forget(dummy); + ret + } +} + +#[no_mangle] +pub fn create_async_code() -> AsyncStatus { + AsyncStatus( + RustFuture::new(Box::new(async { + crate::println!("waiting 2 secs"); + crate::task::wait(2.0).await; + crate::println!("waiting 0.4 secs"); + crate::task::wait(0.4).await; + crate::println!("returning"); + 16 + })), + RustFuture::poll_future, + ) +} + +#[repr(C)] +pub(crate) struct RustFuture(u32); + +impl RustFuture { + pub fn new(future: Box>) -> RustFuture { + unsafe { + let raw = Box::into_raw(future); + + let task = Rc::new(RustFutureTask { + task_id: new_task(), + waker: RefCell::new(None), + future: raw as *mut dyn Future as *mut dyn Future, + }); + + task.waker + .replace(Some(Waker::from_raw(task.clone().raw_waker()))); + + TASKS.with(|cell| { + let mut borrow = cell.borrow_mut(); + borrow.push(task.clone()); + }); + + RustFuture(task.task_id) + } + } + + pub(crate) unsafe extern "C" fn poll_future(id: u32) -> TaskResult { + TASKS.with(|cell| { + let task = { + let tasks = cell.borrow(); + if let Some(task) = tasks.iter().find(|v| v.task_id == id) { + task.clone() + } else { + return TaskResult::None; + } + }; + + let waker = task.waker.borrow(); + let mut context = Context::from_waker(waker.as_ref().unwrap()); + + // SAFETY: + // probably not + let mut future = + Pin::new_unchecked(Box::from_raw(task.future as *mut dyn Future)); + + match future.as_mut().poll(&mut context) { + Poll::Pending => { + // We forget the future here because we don't want to drop it yet + std::mem::forget(future); + + TaskResult::None + } + Poll::Ready(data) => { + // Remove this task so that subsequent polls will fail and memory will get cleaned up + // This won't drop the future but since it's in-scope, it'll be dropped anyways + let mut tasks = cell.borrow_mut(); + tasks.retain(|task| task.task_id != id); + + TaskResult::Ready(data) + } + } + }) + } +} diff --git a/src/futures/task.rs b/src/futures/task.rs index 27eb071..75633b1 100644 --- a/src/futures/task.rs +++ b/src/futures/task.rs @@ -6,21 +6,22 @@ use std::{ task::{Context, RawWaker, Waker}, }; -use super::waker::WAKER_VTABLE; +use super::waker::task_waker; pub struct TaskFuture { future: Pin + 'static>>, waker: Waker, } +/// Rust executor pub struct Task { future: RefCell>, queued: Cell, } impl Task { - pub fn new(future: Pin + 'static>>) -> Rc { - let task = Rc::new(Task { + pub fn new(future: Pin + 'static>>) -> Rc { + let task = Rc::new(Self { future: RefCell::new(None), queued: Cell::new(false), }); @@ -39,7 +40,7 @@ impl Task { } pub fn raw_waker(self: Rc) -> RawWaker { - RawWaker::new(Rc::into_raw(self) as *const (), &WAKER_VTABLE) + RawWaker::new(Rc::into_raw(self) as *const (), &task_waker::WAKER) } pub fn execute(&self) { @@ -59,3 +60,45 @@ impl Task { } } } + +// #[repr(C)] +// pub enum TaskResult { +// Ready(T), +// None, +// } + +// Lua executor +// We don't store the waker as it is up to the future to store it +// pub struct LuaTask { +// task_id: u32, +// future: Pin + 'static>>, +// } + +// impl LuaTask { +// pub fn wake_by_ref(self: &Rc) { +// unsafe { wake_task(self.task_id) }; +// } + +// pub fn raw_waker(self: Rc) -> RawWaker { +// RawWaker::new(Rc::into_raw(self) as *const (), &lua_task_waker::WAKER) +// } +// } + +// rust bindings pass closure that returns FfiFuture + +// (nevermind) lua code creates LuaTask with a unique id (createPointer(awakenFunc)) + +// rust bindings call new_task which is passed with FfiFuture +// lua bindings update that pointer with the awaker + +// rust code calls wake_task with custom waker +// lua code awakenFunc is called and the closure's poll function is called (passed from async closures) + +// impl Drop for LuaTask { +// fn drop(&mut self) { +// TASKS.with(|v| { +// let mut tasks = v.borrow_mut(); +// tasks.retain(|v| v.task_id != self.task_id); +// }); +// } +// } diff --git a/src/futures/waker.rs b/src/futures/waker.rs index e4c7a7c..3c56274 100644 --- a/src/futures/waker.rs +++ b/src/futures/waker.rs @@ -1,31 +1,40 @@ -use std::{ - mem::forget, - rc::Rc, - task::{RawWaker, RawWakerVTable}, -}; +macro_rules! waker { + ($name:ident $ty:ty) => { + pub(super) mod $name { + #[allow(unused_imports)] + use super::super::{ffi::RustFutureTask, task::Task}; + use std::{ + mem::forget, + rc::Rc, + task::{RawWaker, RawWakerVTable}, + }; -use super::task::Task; + unsafe fn clone(ptr: *const ()) -> RawWaker { + let ptr = Rc::from_raw(ptr as *const $ty); + let raw_waker = ptr.clone().raw_waker(); + forget(ptr); + raw_waker + } -unsafe fn clone(ptr: *const ()) -> RawWaker { - let ptr = Rc::from_raw(ptr as *const Task); - let raw_waker = ptr.clone().raw_waker(); - forget(ptr); - raw_waker -} + unsafe fn wake(ptr: *const ()) { + let ptr = Rc::from_raw(ptr as *const $ty); + ptr.wake_by_ref(); + } -unsafe fn wake(ptr: *const ()) { - let ptr = Rc::from_raw(ptr as *const Task); - ptr.wake_by_ref(); -} + unsafe fn wake_by_ref(ptr: *const ()) { + let ptr = Rc::from_raw(ptr as *const $ty); + ptr.wake_by_ref(); + forget(ptr); + } -unsafe fn wake_by_ref(ptr: *const ()) { - let ptr = Rc::from_raw(ptr as *const Task); - ptr.wake_by_ref(); - forget(ptr); -} + unsafe fn drop(ptr: *const ()) { + Rc::from_raw(ptr as *const $ty); + } -unsafe fn drop(ptr: *const ()) { - Rc::from_raw(ptr as *const Task); + pub const WAKER: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); + } + }; } -pub(super) const WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); +waker!(task_waker Task); +waker!(lua_task_waker RustFutureTask); diff --git a/src/generated.rs b/src/generated.rs index e194563..a79470b 100644 --- a/src/generated.rs +++ b/src/generated.rs @@ -1 +1,6 @@ +use super::*; +use crate::futures::ffi::*; +use std::future::Future; +use std::rc::Rc; + include!(concat!(env!("OUT_DIR"), "/generated.rs")); diff --git a/src/lib.rs b/src/lib.rs index ba024ac..de84377 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![allow(incomplete_features)] #![feature(async_fn_in_trait)] +mod conversion; pub mod datatypes; pub mod futures; pub mod generated; diff --git a/src/libraries/standard.rs b/src/libraries/standard.rs index 050baa6..23848bd 100644 --- a/src/libraries/standard.rs +++ b/src/libraries/standard.rs @@ -9,6 +9,6 @@ extern "C" { #[macro_export] macro_rules! println { ($($tts:tt)*) => { - unsafe {{ roblox_print(&format!($($tts)*)) }}; + unsafe {{ $crate::roblox_print(&format!($($tts)*)) }}; } } From b5b6c7152dbcafa5838aa81e35983985e643a16b Mon Sep 17 00:00:00 2001 From: fireboltofdeath <24422634+Fireboltofdeath@users.noreply.github.com> Date: Tue, 20 Jun 2023 15:54:09 -0400 Subject: [PATCH 3/5] Add async and non-async variants of every event/callback --- build/dump/mod.rs | 126 ++-- roblox/abi.luau | 1714 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1791 insertions(+), 49 deletions(-) diff --git a/build/dump/mod.rs b/build/dump/mod.rs index f29747c..3f1f5d5 100644 --- a/build/dump/mod.rs +++ b/build/dump/mod.rs @@ -240,13 +240,13 @@ fn transform_class_function( }) } -fn transform_class_event(dump: &Dump, event: &ClassEventMember) -> Option { +fn transform_class_event(dump: &Dump, event: &ClassEventMember) -> Vec { if !event .parameters .iter() .all(|parameter| is_type_generated(dump, ¶meter.value_type)) { - return None; + return vec![]; } let inputs = event @@ -260,36 +260,55 @@ fn transform_class_event(dump: &Dump, event: &ClassEventMember) -> Option>(); - Some(Member { - flags: MemberFlags { - deprecated: event.tags.contains("Deprecated"), - ..MemberFlags::default() + vec![ + Member { + flags: MemberFlags { + deprecated: event.tags.contains("Deprecated"), + ..MemberFlags::default() + }, + implementation: implementations::Event.into(), + api_name: event.name.clone(), + name: format!("on_{}_async", to_snake(&event.name)), + inputs: vec![ + Parameter::new("self", CodegenKind::Instance("Instance".to_string())), + Parameter::new( + "callback", + CodegenKind::Function(inputs.clone(), Box::new(CodegenKind::Void), Async::Yes), + ), + ], + outputs: vec![CodegenKind::DataType("RbxScriptConnection".to_string())], }, - implementation: implementations::Event.into(), - api_name: event.name.clone(), - name: format!("on_{}", to_snake(&event.name)), - inputs: vec![ - Parameter::new("self", CodegenKind::Instance("Instance".to_string())), - Parameter::new( - "callback", - CodegenKind::Function(inputs, Box::new(CodegenKind::Void), Async::No), - ), - ], - outputs: vec![CodegenKind::DataType("RbxScriptConnection".to_string())], - }) + Member { + flags: MemberFlags { + deprecated: event.tags.contains("Deprecated"), + ..MemberFlags::default() + }, + implementation: implementations::Event.into(), + api_name: event.name.clone(), + name: format!("on_{}", to_snake(&event.name)), + inputs: vec![ + Parameter::new("self", CodegenKind::Instance("Instance".to_string())), + Parameter::new( + "callback", + CodegenKind::Function(inputs, Box::new(CodegenKind::Void), Async::No), + ), + ], + outputs: vec![CodegenKind::DataType("RbxScriptConnection".to_string())], + }, + ] } -fn transform_class_callback(dump: &Dump, callback: &ClassCallbackMember) -> Option { +fn transform_class_callback(dump: &Dump, callback: &ClassCallbackMember) -> Vec { if !callback .parameters .iter() .all(|parameter| is_type_generated(dump, ¶meter.value_type)) { - return None; + return vec![]; } if !is_type_generated(dump, &callback.return_type) { - return None; + return vec![]; } let inputs = callback @@ -303,27 +322,50 @@ fn transform_class_callback(dump: &Dump, callback: &ClassCallbackMember) -> Opti }) .collect::>(); - Some(Member { - flags: MemberFlags { - deprecated: callback.tags.contains("Deprecated"), - ..MemberFlags::default() + vec![ + Member { + flags: MemberFlags { + deprecated: callback.tags.contains("Deprecated"), + ..MemberFlags::default() + }, + implementation: implementations::Callback.into(), + name: format!("on_{}_async", to_snake(&callback.name)), + api_name: callback.name.clone(), + inputs: vec![ + Parameter::new("self", CodegenKind::Instance("Instance".to_string())), + Parameter::new( + "callback", + CodegenKind::Function( + inputs.clone(), + Box::new(transform_value_type(&callback.return_type, false)), + Async::Yes, + ), + ), + ], + outputs: Vec::new(), }, - implementation: implementations::Callback.into(), - name: format!("on_{}", to_snake(&callback.name)), - api_name: callback.name.clone(), - inputs: vec![ - Parameter::new("self", CodegenKind::Instance("Instance".to_string())), - Parameter::new( - "callback", - CodegenKind::Function( - inputs, - Box::new(transform_value_type(&callback.return_type, false)), - Async::Yes, + Member { + flags: MemberFlags { + deprecated: callback.tags.contains("Deprecated"), + ..MemberFlags::default() + }, + implementation: implementations::Callback.into(), + name: format!("on_{}", to_snake(&callback.name)), + api_name: callback.name.clone(), + inputs: vec![ + Parameter::new("self", CodegenKind::Instance("Instance".to_string())), + Parameter::new( + "callback", + CodegenKind::Function( + inputs, + Box::new(transform_value_type(&callback.return_type, false)), + Async::No, + ), ), - ), - ], - outputs: Vec::new(), - }) + ], + outputs: Vec::new(), + }, + ] } fn transform_class_member(dump: &Dump, class: &Class, member: &ClassMember) -> Vec { @@ -337,9 +379,7 @@ fn transform_class_member(dump: &Dump, class: &Class, member: &ClassMember) -> V ClassMember::Function(function) => transform_class_function(dump, class, function) .into_iter() .collect(), - ClassMember::Callback(callback) => transform_class_callback(dump, callback) - .into_iter() - .collect(), + ClassMember::Callback(callback) => transform_class_callback(dump, callback), } } diff --git a/roblox/abi.luau b/roblox/abi.luau index d901ced..8fcc9e6 100644 --- a/roblox/abi.luau +++ b/roblox/abi.luau @@ -160,6 +160,20 @@ function abi.ffi.method_instance_wait_for_child(self, child_name_addr, child_nam end) return future; end +function abi.ffi.event_instance_ancestry_changed_on_ancestry_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AncestryChanged:Connect(function(child, parent) + local child_optional, child_optional_0 = 0, 0; + if (child ~= nil) then + child_optional, child_optional_0 = 1, createPointer(child); + end + local parent_optional, parent_optional_0 = 0, 0; + if (parent ~= nil) then + parent_optional, parent_optional_0 = 1, createPointer(parent); + end + invokeFunction(callback_data, callback_vtable, child_optional, child_optional_0, parent_optional, parent_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_ancestry_changed_on_ancestry_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AncestryChanged:Connect(function(child, parent) local child_optional, child_optional_0 = 0, 0; @@ -174,6 +188,17 @@ function abi.ffi.event_instance_ancestry_changed_on_ancestry_changed(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_instance_attribute_changed_on_attribute_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AttributeChanged:Connect(function(attribute) + local attribute_len = #attribute; + local attribute_content = allocString(attribute_len); + for i = 1, attribute_len do + storeU8(memory, attribute_content + (i - 1), string.byte(attribute:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, attribute_content, attribute_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_attribute_changed_on_attribute_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AttributeChanged:Connect(function(attribute) local attribute_len = #attribute; @@ -185,6 +210,16 @@ function abi.ffi.event_instance_attribute_changed_on_attribute_changed(self, cal end)); return createPointer(result_0); end +function abi.ffi.event_instance_child_added_on_child_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ChildAdded:Connect(function(child) + local child_optional, child_optional_0 = 0, 0; + if (child ~= nil) then + child_optional, child_optional_0 = 1, createPointer(child); + end + invokeFunction(callback_data, callback_vtable, child_optional, child_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_child_added_on_child_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ChildAdded:Connect(function(child) local child_optional, child_optional_0 = 0, 0; @@ -195,6 +230,16 @@ function abi.ffi.event_instance_child_added_on_child_added(self, callback_data, end)); return createPointer(result_0); end +function abi.ffi.event_instance_child_removed_on_child_removed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ChildRemoved:Connect(function(child) + local child_optional, child_optional_0 = 0, 0; + if (child ~= nil) then + child_optional, child_optional_0 = 1, createPointer(child); + end + invokeFunction(callback_data, callback_vtable, child_optional, child_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_child_removed_on_child_removed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ChildRemoved:Connect(function(child) local child_optional, child_optional_0 = 0, 0; @@ -205,6 +250,16 @@ function abi.ffi.event_instance_child_removed_on_child_removed(self, callback_da end)); return createPointer(result_0); end +function abi.ffi.event_instance_descendant_added_on_descendant_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DescendantAdded:Connect(function(descendant) + local descendant_optional, descendant_optional_0 = 0, 0; + if (descendant ~= nil) then + descendant_optional, descendant_optional_0 = 1, createPointer(descendant); + end + invokeFunction(callback_data, callback_vtable, descendant_optional, descendant_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_descendant_added_on_descendant_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DescendantAdded:Connect(function(descendant) local descendant_optional, descendant_optional_0 = 0, 0; @@ -215,6 +270,16 @@ function abi.ffi.event_instance_descendant_added_on_descendant_added(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_instance_descendant_removing_on_descendant_removing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DescendantRemoving:Connect(function(descendant) + local descendant_optional, descendant_optional_0 = 0, 0; + if (descendant ~= nil) then + descendant_optional, descendant_optional_0 = 1, createPointer(descendant); + end + invokeFunction(callback_data, callback_vtable, descendant_optional, descendant_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_descendant_removing_on_descendant_removing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DescendantRemoving:Connect(function(descendant) local descendant_optional, descendant_optional_0 = 0, 0; @@ -225,6 +290,12 @@ function abi.ffi.event_instance_descendant_removing_on_descendant_removing(self, end)); return createPointer(result_0); end +function abi.ffi.event_instance_destroying_on_destroying_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Destroying:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_instance_destroying_on_destroying(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Destroying:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -453,12 +524,29 @@ end function abi.ffi.method_animation_track_stop(self, fade_time) getPointer(self):Stop(fade_time) end +function abi.ffi.event_animation_track_did_loop_on_did_loop_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_animation_track_did_loop_on_did_loop(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_animation_track_keyframe_reached_on_keyframe_reached_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).KeyframeReached:Connect(function(keyframe_name) + local keyframe_name_len = #keyframe_name; + local keyframe_name_content = allocString(keyframe_name_len); + for i = 1, keyframe_name_len do + storeU8(memory, keyframe_name_content + (i - 1), string.byte(keyframe_name:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, keyframe_name_content, keyframe_name_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_animation_track_keyframe_reached_on_keyframe_reached(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).KeyframeReached:Connect(function(keyframe_name) local keyframe_name_len = #keyframe_name; @@ -470,6 +558,12 @@ function abi.ffi.event_animation_track_keyframe_reached_on_keyframe_reached(self end)); return createPointer(result_0); end +function abi.ffi.event_animation_track_stopped_on_stopped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_animation_track_stopped_on_stopped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -491,6 +585,16 @@ function abi.ffi.method_animator_load_animation(self, animation) end return result_0_optional, result_0_optional_0; end +function abi.ffi.event_animator_animation_played_on_animation_played_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AnimationPlayed:Connect(function(animation_track) + local animation_track_optional, animation_track_optional_0 = 0, 0; + if (animation_track ~= nil) then + animation_track_optional, animation_track_optional_0 = 1, createPointer(animation_track); + end + invokeFunction(callback_data, callback_vtable, animation_track_optional, animation_track_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_animator_animation_played_on_animation_played(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AnimationPlayed:Connect(function(animation_track) local animation_track_optional, animation_track_optional_0 = 0, 0; @@ -501,6 +605,12 @@ function abi.ffi.event_animator_animation_played_on_animation_played(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_asset_import_session_upload_progress_on_upload_progress_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UploadProgress:Connect(function(progress_ratio) + invokeFunction(callback_data, callback_vtable, progress_ratio) + end)); + return createPointer(result_0); +end function abi.ffi.event_asset_import_session_upload_progress_on_upload_progress(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UploadProgress:Connect(function(progress_ratio) invokeFunction(callback_data, callback_vtable, progress_ratio) @@ -818,24 +928,52 @@ function abi.ffi.method_avatar_editor_service_search_catalog(self, search_parame end) return future; end +function abi.ffi.event_avatar_editor_service_prompt_allow_inventory_read_access_completed_on_prompt_allow_inventory_read_access_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptAllowInventoryReadAccessCompleted:Connect(function(result) + invokeFunction(callback_data, callback_vtable, result) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_allow_inventory_read_access_completed_on_prompt_allow_inventory_read_access_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptAllowInventoryReadAccessCompleted:Connect(function(result) invokeFunction(callback_data, callback_vtable, result) end)); return createPointer(result_0); end +function abi.ffi.event_avatar_editor_service_prompt_delete_outfit_completed_on_prompt_delete_outfit_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptDeleteOutfitCompleted:Connect(function(result) + invokeFunction(callback_data, callback_vtable, result) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_delete_outfit_completed_on_prompt_delete_outfit_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptDeleteOutfitCompleted:Connect(function(result) invokeFunction(callback_data, callback_vtable, result) end)); return createPointer(result_0); end +function abi.ffi.event_avatar_editor_service_prompt_rename_outfit_completed_on_prompt_rename_outfit_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptRenameOutfitCompleted:Connect(function(result) + invokeFunction(callback_data, callback_vtable, result) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_rename_outfit_completed_on_prompt_rename_outfit_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptRenameOutfitCompleted:Connect(function(result) invokeFunction(callback_data, callback_vtable, result) end)); return createPointer(result_0); end +function abi.ffi.event_avatar_editor_service_prompt_save_avatar_completed_on_prompt_save_avatar_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSaveAvatarCompleted:Connect(function(result, humanoid_description) + local humanoid_description_optional, humanoid_description_optional_0 = 0, 0; + if (humanoid_description ~= nil) then + humanoid_description_optional, humanoid_description_optional_0 = 1, createPointer(humanoid_description); + end + invokeFunction(callback_data, callback_vtable, result, humanoid_description_optional, humanoid_description_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_save_avatar_completed_on_prompt_save_avatar_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSaveAvatarCompleted:Connect(function(result, humanoid_description) local humanoid_description_optional, humanoid_description_optional_0 = 0, 0; @@ -846,12 +984,24 @@ function abi.ffi.event_avatar_editor_service_prompt_save_avatar_completed_on_pro end)); return createPointer(result_0); end +function abi.ffi.event_avatar_editor_service_prompt_set_favorite_completed_on_prompt_set_favorite_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSetFavoriteCompleted:Connect(function(result) + invokeFunction(callback_data, callback_vtable, result) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_set_favorite_completed_on_prompt_set_favorite_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSetFavoriteCompleted:Connect(function(result) invokeFunction(callback_data, callback_vtable, result) end)); return createPointer(result_0); end +function abi.ffi.event_avatar_editor_service_prompt_update_outfit_completed_on_prompt_update_outfit_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptUpdateOutfitCompleted:Connect(function(result) + invokeFunction(callback_data, callback_vtable, result) + end)); + return createPointer(result_0); +end function abi.ffi.event_avatar_editor_service_prompt_update_outfit_completed_on_prompt_update_outfit_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptUpdateOutfitCompleted:Connect(function(result) invokeFunction(callback_data, callback_vtable, result) @@ -946,18 +1096,40 @@ end function abi.ffi.method_tool_deactivate(self) getPointer(self):Deactivate() end +function abi.ffi.event_tool_activated_on_activated_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Activated:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_tool_activated_on_activated(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Activated:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_tool_deactivated_on_deactivated_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Deactivated:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_tool_deactivated_on_deactivated(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Deactivated:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_tool_equipped_on_equipped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Equipped:Connect(function(mouse) + local mouse_optional, mouse_optional_0 = 0, 0; + if (mouse ~= nil) then + mouse_optional, mouse_optional_0 = 1, createPointer(mouse); + end + invokeFunction(callback_data, callback_vtable, mouse_optional, mouse_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_tool_equipped_on_equipped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Equipped:Connect(function(mouse) local mouse_optional, mouse_optional_0 = 0, 0; @@ -968,6 +1140,12 @@ function abi.ffi.event_tool_equipped_on_equipped(self, callback_data, callback_v end)); return createPointer(result_0); end +function abi.ffi.event_tool_unequipped_on_unequipped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Unequipped:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_tool_unequipped_on_unequipped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Unequipped:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -1388,6 +1566,12 @@ function abi.ffi.method_body_position_get_last_force(self) local result_0 = getPointer(self):GetLastForce(); return createPointer(result_0); end +function abi.ffi.event_body_position_reached_target_on_reached_target_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReachedTarget:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_body_position_reached_target_on_reached_target(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReachedTarget:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -1520,6 +1704,12 @@ end function abi.ffi.method_rocket_propulsion_fire(self) getPointer(self):Fire() end +function abi.ffi.event_rocket_propulsion_reached_target_on_reached_target_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReachedTarget:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_rocket_propulsion_reached_target_on_reached_target(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReachedTarget:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -1638,6 +1828,12 @@ function abi.ffi.method_camera_viewport_point_to_ray(self, x, y, depth) local result_0 = getPointer(self):ViewportPointToRay(x, y, depth); return createPointer(result_0); end +function abi.ffi.event_camera_interpolation_finished_on_interpolation_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InterpolationFinished:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_camera_interpolation_finished_on_interpolation_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InterpolationFinished:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -1864,6 +2060,21 @@ function abi.ffi.method_chat_filter_string_for_broadcast(self, string_to_filter_ end) return future; end +function abi.ffi.event_chat_chatted_on_chatted_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Chatted:Connect(function(part, message, color) + local part_optional, part_optional_0 = 0, 0; + if (part ~= nil) then + part_optional, part_optional_0 = 1, createPointer(part); + end + local message_len = #message; + local message_content = allocString(message_len); + for i = 1, message_len do + storeU8(memory, message_content + (i - 1), string.byte(message:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, part_optional, part_optional_0, message_content, message_len, color) + end)); + return createPointer(result_0); +end function abi.ffi.event_chat_chatted_on_chatted(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Chatted:Connect(function(part, message, color) local part_optional, part_optional_0 = 0, 0; @@ -1893,6 +2104,16 @@ end function abi.ffi.property_setter_click_detector_max_activation_distance_set_max_activation_distance(self, value) getPointer(self).MaxActivationDistance = value; end +function abi.ffi.event_click_detector_mouse_click_on_mouse_click_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseClick:Connect(function(player_who_clicked) + local player_who_clicked_optional, player_who_clicked_optional_0 = 0, 0; + if (player_who_clicked ~= nil) then + player_who_clicked_optional, player_who_clicked_optional_0 = 1, createPointer(player_who_clicked); + end + invokeFunction(callback_data, callback_vtable, player_who_clicked_optional, player_who_clicked_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_click_detector_mouse_click_on_mouse_click(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseClick:Connect(function(player_who_clicked) local player_who_clicked_optional, player_who_clicked_optional_0 = 0, 0; @@ -1903,6 +2124,16 @@ function abi.ffi.event_click_detector_mouse_click_on_mouse_click(self, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_click_detector_mouse_hover_enter_on_mouse_hover_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseHoverEnter:Connect(function(player_who_hovered) + local player_who_hovered_optional, player_who_hovered_optional_0 = 0, 0; + if (player_who_hovered ~= nil) then + player_who_hovered_optional, player_who_hovered_optional_0 = 1, createPointer(player_who_hovered); + end + invokeFunction(callback_data, callback_vtable, player_who_hovered_optional, player_who_hovered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_click_detector_mouse_hover_enter_on_mouse_hover_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseHoverEnter:Connect(function(player_who_hovered) local player_who_hovered_optional, player_who_hovered_optional_0 = 0, 0; @@ -1913,6 +2144,16 @@ function abi.ffi.event_click_detector_mouse_hover_enter_on_mouse_hover_enter(sel end)); return createPointer(result_0); end +function abi.ffi.event_click_detector_mouse_hover_leave_on_mouse_hover_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseHoverLeave:Connect(function(player_who_hovered) + local player_who_hovered_optional, player_who_hovered_optional_0 = 0, 0; + if (player_who_hovered ~= nil) then + player_who_hovered_optional, player_who_hovered_optional_0 = 1, createPointer(player_who_hovered); + end + invokeFunction(callback_data, callback_vtable, player_who_hovered_optional, player_who_hovered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_click_detector_mouse_hover_leave_on_mouse_hover_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseHoverLeave:Connect(function(player_who_hovered) local player_who_hovered_optional, player_who_hovered_optional_0 = 0, 0; @@ -1923,6 +2164,16 @@ function abi.ffi.event_click_detector_mouse_hover_leave_on_mouse_hover_leave(sel end)); return createPointer(result_0); end +function abi.ffi.event_click_detector_right_mouse_click_on_right_mouse_click_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).RightMouseClick:Connect(function(player_who_clicked) + local player_who_clicked_optional, player_who_clicked_optional_0 = 0, 0; + if (player_who_clicked ~= nil) then + player_who_clicked_optional, player_who_clicked_optional_0 = 1, createPointer(player_who_clicked); + end + invokeFunction(callback_data, callback_vtable, player_who_clicked_optional, player_who_clicked_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_click_detector_right_mouse_click_on_right_mouse_click(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).RightMouseClick:Connect(function(player_who_clicked) local player_who_clicked_optional, player_who_clicked_optional_0 = 0, 0; @@ -1971,6 +2222,17 @@ end function abi.ffi.method_collection_service_remove_tag(self, instance, tag_addr, tag_len) getPointer(self):RemoveTag(getPointer(instance), loadString(memory, tag_addr, tag_len)) end +function abi.ffi.event_collection_service_tag_added_on_tag_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TagAdded:Connect(function(tag) + local tag_len = #tag; + local tag_content = allocString(tag_len); + for i = 1, tag_len do + storeU8(memory, tag_content + (i - 1), string.byte(tag:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, tag_content, tag_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_collection_service_tag_added_on_tag_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TagAdded:Connect(function(tag) local tag_len = #tag; @@ -1982,6 +2244,17 @@ function abi.ffi.event_collection_service_tag_added_on_tag_added(self, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_collection_service_tag_removed_on_tag_removed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TagRemoved:Connect(function(tag) + local tag_len = #tag; + local tag_content = allocString(tag_len); + for i = 1, tag_len do + storeU8(memory, tag_content + (i - 1), string.byte(tag:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, tag_content, tag_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_collection_service_tag_removed_on_tag_removed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TagRemoved:Connect(function(tag) local tag_len = #tag; @@ -3031,6 +3304,12 @@ end function abi.ffi.method_content_provider_unregister_encrypted_asset(self, asset_id) getPointer(self):UnregisterEncryptedAsset(getPointer(asset_id)) end +function abi.ffi.event_content_provider_asset_fetch_failed_on_asset_fetch_failed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AssetFetchFailed:Connect(function(asset_id) + invokeFunction(callback_data, callback_vtable, createPointer(asset_id)) + end)); + return createPointer(result_0); +end function abi.ffi.event_content_provider_asset_fetch_failed_on_asset_fetch_failed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AssetFetchFailed:Connect(function(asset_id) invokeFunction(callback_data, callback_vtable, createPointer(asset_id)) @@ -3083,6 +3362,16 @@ function abi.ffi.method_context_action_service_get_button(self, action_name_addr end) return future; end +function abi.ffi.event_context_action_service_local_tool_equipped_on_local_tool_equipped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LocalToolEquipped:Connect(function(tool_equipped) + local tool_equipped_optional, tool_equipped_optional_0 = 0, 0; + if (tool_equipped ~= nil) then + tool_equipped_optional, tool_equipped_optional_0 = 1, createPointer(tool_equipped); + end + invokeFunction(callback_data, callback_vtable, tool_equipped_optional, tool_equipped_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_context_action_service_local_tool_equipped_on_local_tool_equipped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LocalToolEquipped:Connect(function(tool_equipped) local tool_equipped_optional, tool_equipped_optional_0 = 0, 0; @@ -3093,7 +3382,17 @@ function abi.ffi.event_context_action_service_local_tool_equipped_on_local_tool_ end)); return createPointer(result_0); end -function abi.ffi.event_context_action_service_local_tool_unequipped_on_local_tool_unequipped(self, callback_data, callback_vtable) +function abi.ffi.event_context_action_service_local_tool_unequipped_on_local_tool_unequipped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LocalToolUnequipped:Connect(function(tool_unequipped) + local tool_unequipped_optional, tool_unequipped_optional_0 = 0, 0; + if (tool_unequipped ~= nil) then + tool_unequipped_optional, tool_unequipped_optional_0 = 1, createPointer(tool_unequipped); + end + invokeFunction(callback_data, callback_vtable, tool_unequipped_optional, tool_unequipped_optional_0) + end)); + return createPointer(result_0); +end +function abi.ffi.event_context_action_service_local_tool_unequipped_on_local_tool_unequipped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LocalToolUnequipped:Connect(function(tool_unequipped) local tool_unequipped_optional, tool_unequipped_optional_0 = 0, 0; if (tool_unequipped ~= nil) then @@ -3113,6 +3412,12 @@ end function abi.ffi.method_controller_unbind_button(self, button) getPointer(self):UnbindButton(button) end +function abi.ffi.event_controller_button_changed_on_button_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ButtonChanged:Connect(function(button) + invokeFunction(callback_data, callback_vtable, button) + end)); + return createPointer(result_0); +end function abi.ffi.event_controller_button_changed_on_button_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ButtonChanged:Connect(function(button) invokeFunction(callback_data, callback_vtable, button) @@ -3127,6 +3432,17 @@ function abi.ffi.property_getter_skateboard_controller_throttle(self) local result_0 = getPointer(self).Throttle; return result_0; end +function abi.ffi.event_skateboard_controller_axis_changed_on_axis_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AxisChanged:Connect(function(axis) + local axis_len = #axis; + local axis_content = allocString(axis_len); + for i = 1, axis_len do + storeU8(memory, axis_content + (i - 1), string.byte(axis:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, axis_content, axis_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_skateboard_controller_axis_changed_on_axis_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).AxisChanged:Connect(function(axis) local axis_len = #axis; @@ -3613,6 +3929,20 @@ end function abi.ffi.property_setter_dialog_trigger_offset_set_trigger_offset(self, value) getPointer(self).TriggerOffset = getPointer(value); end +function abi.ffi.event_dialog_dialog_choice_selected_on_dialog_choice_selected_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DialogChoiceSelected:Connect(function(player, dialog_choice) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + local dialog_choice_optional, dialog_choice_optional_0 = 0, 0; + if (dialog_choice ~= nil) then + dialog_choice_optional, dialog_choice_optional_0 = 1, createPointer(dialog_choice); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, dialog_choice_optional, dialog_choice_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_dialog_dialog_choice_selected_on_dialog_choice_selected(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DialogChoiceSelected:Connect(function(player, dialog_choice) local player_optional, player_optional_0 = 0, 0; @@ -3864,6 +4194,16 @@ end function abi.ffi.property_setter_explosion_visible_set_visible(self, value) getPointer(self).Visible = value == 1; end +function abi.ffi.event_explosion_hit_on_hit_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Hit:Connect(function(part, distance) + local part_optional, part_optional_0 = 0, 0; + if (part ~= nil) then + part_optional, part_optional_0 = 1, createPointer(part); + end + invokeFunction(callback_data, callback_vtable, part_optional, part_optional_0, distance) + end)); + return createPointer(result_0); +end function abi.ffi.event_explosion_hit_on_hit(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Hit:Connect(function(part, distance) local part_optional, part_optional_0 = 0, 0; @@ -4206,6 +4546,20 @@ end function abi.ffi.property_setter_gui_base_2_d_selection_group_set_selection_group(self, value) getPointer(self).SelectionGroup = value == 1; end +function abi.ffi.event_gui_base_2_d_selection_changed_on_selection_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionChanged:Connect(function(am_i_selected, previous_selection, new_selection) + local previous_selection_optional, previous_selection_optional_0 = 0, 0; + if (previous_selection ~= nil) then + previous_selection_optional, previous_selection_optional_0 = 1, createPointer(previous_selection); + end + local new_selection_optional, new_selection_optional_0 = 0, 0; + if (new_selection ~= nil) then + new_selection_optional, new_selection_optional_0 = 1, createPointer(new_selection); + end + invokeFunction(callback_data, callback_vtable, am_i_selected and 1 or 0, previous_selection_optional, previous_selection_optional_0, new_selection_optional, new_selection_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_base_2_d_selection_changed_on_selection_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionChanged:Connect(function(am_i_selected, previous_selection, new_selection) local previous_selection_optional, previous_selection_optional_0 = 0, 0; @@ -4408,6 +4762,16 @@ end function abi.ffi.property_setter_gui_object_z_index_set_z_index(self, value) getPointer(self).ZIndex = value; end +function abi.ffi.event_gui_object_input_began_on_input_began_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputBegan:Connect(function(input) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_input_began_on_input_began(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputBegan:Connect(function(input) local input_optional, input_optional_0 = 0, 0; @@ -4418,6 +4782,16 @@ function abi.ffi.event_gui_object_input_began_on_input_began(self, callback_data end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_input_changed_on_input_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputChanged:Connect(function(input) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_input_changed_on_input_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputChanged:Connect(function(input) local input_optional, input_optional_0 = 0, 0; @@ -4428,6 +4802,16 @@ function abi.ffi.event_gui_object_input_changed_on_input_changed(self, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_input_ended_on_input_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputEnded:Connect(function(input) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_input_ended_on_input_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputEnded:Connect(function(input) local input_optional, input_optional_0 = 0, 0; @@ -4438,48 +4822,96 @@ function abi.ffi.event_gui_object_input_ended_on_input_ended(self, callback_data end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_mouse_enter_on_mouse_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_mouse_enter_on_mouse_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_mouse_leave_on_mouse_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_mouse_leave_on_mouse_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_mouse_moved_on_mouse_moved_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseMoved:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_mouse_moved_on_mouse_moved(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseMoved:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_mouse_wheel_backward_on_mouse_wheel_backward_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseWheelBackward:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_mouse_wheel_backward_on_mouse_wheel_backward(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseWheelBackward:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_mouse_wheel_forward_on_mouse_wheel_forward_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseWheelForward:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_mouse_wheel_forward_on_mouse_wheel_forward(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseWheelForward:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_selection_gained_on_selection_gained_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionGained:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_selection_gained_on_selection_gained(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionGained:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_selection_lost_on_selection_lost_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionLost:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_selection_lost_on_selection_lost(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SelectionLost:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_gui_object_touch_swipe_on_touch_swipe_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchSwipe:Connect(function(swipe_direction, number_of_touches) + invokeFunction(callback_data, callback_vtable, swipe_direction, number_of_touches) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_object_touch_swipe_on_touch_swipe(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchSwipe:Connect(function(swipe_direction, number_of_touches) invokeFunction(callback_data, callback_vtable, swipe_direction, number_of_touches) @@ -4535,6 +4967,16 @@ end function abi.ffi.property_setter_gui_button_style_set_style(self, value) getPointer(self).Style = value; end +function abi.ffi.event_gui_button_activated_on_activated_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Activated:Connect(function(input_object, click_count) + local input_object_optional, input_object_optional_0 = 0, 0; + if (input_object ~= nil) then + input_object_optional, input_object_optional_0 = 1, createPointer(input_object); + end + invokeFunction(callback_data, callback_vtable, input_object_optional, input_object_optional_0, click_count) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_activated_on_activated(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Activated:Connect(function(input_object, click_count) local input_object_optional, input_object_optional_0 = 0, 0; @@ -4545,36 +4987,72 @@ function abi.ffi.event_gui_button_activated_on_activated(self, callback_data, ca end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_1_click_on_mouse_button_1_click_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Click:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_1_click_on_mouse_button_1_click(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Click:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_1_down_on_mouse_button_1_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_1_down_on_mouse_button_1_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_1_up_on_mouse_button_1_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_1_up_on_mouse_button_1_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_2_click_on_mouse_button_2_click_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Click:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_2_click_on_mouse_button_2_click(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Click:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_2_down_on_mouse_button_2_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Down:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_2_down_on_mouse_button_2_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Down:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) end)); return createPointer(result_0); end +function abi.ffi.event_gui_button_mouse_button_2_up_on_mouse_button_2_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Up:Connect(function(x, y) + invokeFunction(callback_data, callback_vtable, x, y) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_button_mouse_button_2_up_on_mouse_button_2_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton2Up:Connect(function(x, y) invokeFunction(callback_data, callback_vtable, x, y) @@ -5347,6 +5825,16 @@ end function abi.ffi.method_text_box_release_focus(self, submitted) getPointer(self):ReleaseFocus(submitted == 1) end +function abi.ffi.event_text_box_focus_lost_on_focus_lost_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FocusLost:Connect(function(enter_pressed, input_that_caused_focus_loss) + local input_that_caused_focus_loss_optional, input_that_caused_focus_loss_optional_0 = 0, 0; + if (input_that_caused_focus_loss ~= nil) then + input_that_caused_focus_loss_optional, input_that_caused_focus_loss_optional_0 = 1, createPointer(input_that_caused_focus_loss); + end + invokeFunction(callback_data, callback_vtable, enter_pressed and 1 or 0, input_that_caused_focus_loss_optional, input_that_caused_focus_loss_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_box_focus_lost_on_focus_lost(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FocusLost:Connect(function(enter_pressed, input_that_caused_focus_loss) local input_that_caused_focus_loss_optional, input_that_caused_focus_loss_optional_0 = 0, 0; @@ -5357,12 +5845,24 @@ function abi.ffi.event_text_box_focus_lost_on_focus_lost(self, callback_data, ca end)); return createPointer(result_0); end +function abi.ffi.event_text_box_focused_on_focused_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Focused:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_box_focused_on_focused(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Focused:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_text_box_return_pressed_from_on_screen_keyboard_on_return_pressed_from_on_screen_keyboard_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReturnPressedFromOnScreenKeyboard:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_box_return_pressed_from_on_screen_keyboard_on_return_pressed_from_on_screen_keyboard(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ReturnPressedFromOnScreenKeyboard:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -5422,6 +5922,17 @@ end function abi.ffi.method_video_frame_play(self) getPointer(self):Play() end +function abi.ffi.event_video_frame_did_loop_on_did_loop_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function(video) + local video_len = #video; + local video_content = allocString(video_len); + for i = 1, video_len do + storeU8(memory, video_content + (i - 1), string.byte(video:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, video_content, video_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_video_frame_did_loop_on_did_loop(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function(video) local video_len = #video; @@ -5433,6 +5944,17 @@ function abi.ffi.event_video_frame_did_loop_on_did_loop(self, callback_data, cal end)); return createPointer(result_0); end +function abi.ffi.event_video_frame_ended_on_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ended:Connect(function(video) + local video_len = #video; + local video_content = allocString(video_len); + for i = 1, video_len do + storeU8(memory, video_content + (i - 1), string.byte(video:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, video_content, video_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_video_frame_ended_on_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ended:Connect(function(video) local video_len = #video; @@ -5444,6 +5966,17 @@ function abi.ffi.event_video_frame_ended_on_ended(self, callback_data, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_video_frame_loaded_on_loaded_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function(video) + local video_len = #video; + local video_content = allocString(video_len); + for i = 1, video_len do + storeU8(memory, video_content + (i - 1), string.byte(video:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, video_content, video_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_video_frame_loaded_on_loaded(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function(video) local video_len = #video; @@ -5455,6 +5988,17 @@ function abi.ffi.event_video_frame_loaded_on_loaded(self, callback_data, callbac end)); return createPointer(result_0); end +function abi.ffi.event_video_frame_paused_on_paused_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Paused:Connect(function(video) + local video_len = #video; + local video_content = allocString(video_len); + for i = 1, video_len do + storeU8(memory, video_content + (i - 1), string.byte(video:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, video_content, video_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_video_frame_paused_on_paused(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Paused:Connect(function(video) local video_len = #video; @@ -5466,6 +6010,17 @@ function abi.ffi.event_video_frame_paused_on_paused(self, callback_data, callbac end)); return createPointer(result_0); end +function abi.ffi.event_video_frame_played_on_played_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Played:Connect(function(video) + local video_len = #video; + local video_content = allocString(video_len); + for i = 1, video_len do + storeU8(memory, video_content + (i - 1), string.byte(video:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, video_content, video_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_video_frame_played_on_played(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Played:Connect(function(video) local video_len = #video; @@ -5897,24 +6452,48 @@ end function abi.ffi.property_setter_handle_adornment_z_index_set_z_index(self, value) getPointer(self).ZIndex = value; end +function abi.ffi.event_handle_adornment_mouse_button_1_down_on_mouse_button_1_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_handle_adornment_mouse_button_1_down_on_mouse_button_1_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_handle_adornment_mouse_button_1_up_on_mouse_button_1_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_handle_adornment_mouse_button_1_up_on_mouse_button_1_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_handle_adornment_mouse_enter_on_mouse_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_handle_adornment_mouse_enter_on_mouse_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_handle_adornment_mouse_leave_on_mouse_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_handle_adornment_mouse_leave_on_mouse_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -6043,30 +6622,60 @@ end function abi.ffi.property_setter_arc_handles_axes_set_axes(self, value) getPointer(self).Axes = getPointer(value); end -function abi.ffi.event_arc_handles_mouse_button_1_down_on_mouse_button_1_down(self, callback_data, callback_vtable) +function abi.ffi.event_arc_handles_mouse_button_1_down_on_mouse_button_1_down_async(self, callback_data, callback_vtable, callback_poll) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(axis) invokeFunction(callback_data, callback_vtable, axis) end)); return createPointer(result_0); end +function abi.ffi.event_arc_handles_mouse_button_1_down_on_mouse_button_1_down(self, callback_data, callback_vtable) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(axis) + invokeFunction(callback_data, callback_vtable, axis) + end)); + return createPointer(result_0); +end +function abi.ffi.event_arc_handles_mouse_button_1_up_on_mouse_button_1_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(axis) + invokeFunction(callback_data, callback_vtable, axis) + end)); + return createPointer(result_0); +end function abi.ffi.event_arc_handles_mouse_button_1_up_on_mouse_button_1_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(axis) invokeFunction(callback_data, callback_vtable, axis) end)); return createPointer(result_0); end +function abi.ffi.event_arc_handles_mouse_drag_on_mouse_drag_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseDrag:Connect(function(axis, relative_angle, delta_radius) + invokeFunction(callback_data, callback_vtable, axis, relative_angle, delta_radius) + end)); + return createPointer(result_0); +end function abi.ffi.event_arc_handles_mouse_drag_on_mouse_drag(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseDrag:Connect(function(axis, relative_angle, delta_radius) invokeFunction(callback_data, callback_vtable, axis, relative_angle, delta_radius) end)); return createPointer(result_0); end +function abi.ffi.event_arc_handles_mouse_enter_on_mouse_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(axis) + invokeFunction(callback_data, callback_vtable, axis) + end)); + return createPointer(result_0); +end function abi.ffi.event_arc_handles_mouse_enter_on_mouse_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(axis) invokeFunction(callback_data, callback_vtable, axis) end)); return createPointer(result_0); end +function abi.ffi.event_arc_handles_mouse_leave_on_mouse_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(axis) + invokeFunction(callback_data, callback_vtable, axis) + end)); + return createPointer(result_0); +end function abi.ffi.event_arc_handles_mouse_leave_on_mouse_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(axis) invokeFunction(callback_data, callback_vtable, axis) @@ -6087,30 +6696,60 @@ end function abi.ffi.property_setter_handles_style_set_style(self, value) getPointer(self).Style = value; end +function abi.ffi.event_handles_mouse_button_1_down_on_mouse_button_1_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(face) + invokeFunction(callback_data, callback_vtable, face) + end)); + return createPointer(result_0); +end function abi.ffi.event_handles_mouse_button_1_down_on_mouse_button_1_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Down:Connect(function(face) invokeFunction(callback_data, callback_vtable, face) end)); return createPointer(result_0); end +function abi.ffi.event_handles_mouse_button_1_up_on_mouse_button_1_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(face) + invokeFunction(callback_data, callback_vtable, face) + end)); + return createPointer(result_0); +end function abi.ffi.event_handles_mouse_button_1_up_on_mouse_button_1_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseButton1Up:Connect(function(face) invokeFunction(callback_data, callback_vtable, face) end)); return createPointer(result_0); end +function abi.ffi.event_handles_mouse_drag_on_mouse_drag_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseDrag:Connect(function(face, distance) + invokeFunction(callback_data, callback_vtable, face, distance) + end)); + return createPointer(result_0); +end function abi.ffi.event_handles_mouse_drag_on_mouse_drag(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseDrag:Connect(function(face, distance) invokeFunction(callback_data, callback_vtable, face, distance) end)); return createPointer(result_0); end +function abi.ffi.event_handles_mouse_enter_on_mouse_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(face) + invokeFunction(callback_data, callback_vtable, face) + end)); + return createPointer(result_0); +end function abi.ffi.event_handles_mouse_enter_on_mouse_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseEnter:Connect(function(face) invokeFunction(callback_data, callback_vtable, face) end)); return createPointer(result_0); end +function abi.ffi.event_handles_mouse_leave_on_mouse_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(face) + invokeFunction(callback_data, callback_vtable, face) + end)); + return createPointer(result_0); +end function abi.ffi.event_handles_mouse_leave_on_mouse_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MouseLeave:Connect(function(face) invokeFunction(callback_data, callback_vtable, face) @@ -6221,12 +6860,24 @@ end function abi.ffi.method_gui_service_set_inspect_menu_enabled(self, enabled) getPointer(self):SetInspectMenuEnabled(enabled == 1) end +function abi.ffi.event_gui_service_menu_closed_on_menu_closed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MenuClosed:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_service_menu_closed_on_menu_closed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MenuClosed:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_gui_service_menu_opened_on_menu_opened_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MenuOpened:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_gui_service_menu_opened_on_menu_opened(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MenuOpened:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -6616,72 +7267,148 @@ function abi.ffi.method_humanoid_play_emote(self, emote_name_addr, emote_name_le end) return future; end +function abi.ffi.event_humanoid_climbing_on_climbing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Climbing:Connect(function(speed) + invokeFunction(callback_data, callback_vtable, speed) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_climbing_on_climbing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Climbing:Connect(function(speed) invokeFunction(callback_data, callback_vtable, speed) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_died_on_died_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Died:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_died_on_died(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Died:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_falling_down_on_falling_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FallingDown:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_falling_down_on_falling_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FallingDown:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_free_falling_on_free_falling_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FreeFalling:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_free_falling_on_free_falling(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FreeFalling:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_getting_up_on_getting_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GettingUp:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_getting_up_on_getting_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GettingUp:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_health_changed_on_health_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).HealthChanged:Connect(function(health) + invokeFunction(callback_data, callback_vtable, health) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_health_changed_on_health_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).HealthChanged:Connect(function(health) invokeFunction(callback_data, callback_vtable, health) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_jumping_on_jumping_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Jumping:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_jumping_on_jumping(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Jumping:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_move_to_finished_on_move_to_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MoveToFinished:Connect(function(reached) + invokeFunction(callback_data, callback_vtable, reached and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_move_to_finished_on_move_to_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MoveToFinished:Connect(function(reached) invokeFunction(callback_data, callback_vtable, reached and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_platform_standing_on_platform_standing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlatformStanding:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_platform_standing_on_platform_standing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlatformStanding:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_ragdoll_on_ragdoll_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ragdoll:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_ragdoll_on_ragdoll(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ragdoll:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_running_on_running_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Running:Connect(function(speed) + invokeFunction(callback_data, callback_vtable, speed) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_running_on_running(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Running:Connect(function(speed) invokeFunction(callback_data, callback_vtable, speed) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_seated_on_seated_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Seated:Connect(function(active, current_seat_part) + local current_seat_part_optional, current_seat_part_optional_0 = 0, 0; + if (current_seat_part ~= nil) then + current_seat_part_optional, current_seat_part_optional_0 = 1, createPointer(current_seat_part); + end + invokeFunction(callback_data, callback_vtable, active and 1 or 0, current_seat_part_optional, current_seat_part_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_seated_on_seated(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Seated:Connect(function(active, current_seat_part) local current_seat_part_optional, current_seat_part_optional_0 = 0, 0; @@ -6692,24 +7419,48 @@ function abi.ffi.event_humanoid_seated_on_seated(self, callback_data, callback_v end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_state_changed_on_state_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StateChanged:Connect(function(old, new) + invokeFunction(callback_data, callback_vtable, old, new) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_state_changed_on_state_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StateChanged:Connect(function(old, new) invokeFunction(callback_data, callback_vtable, old, new) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_state_enabled_changed_on_state_enabled_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StateEnabledChanged:Connect(function(state, is_enabled) + invokeFunction(callback_data, callback_vtable, state, is_enabled and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_state_enabled_changed_on_state_enabled_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StateEnabledChanged:Connect(function(state, is_enabled) invokeFunction(callback_data, callback_vtable, state, is_enabled and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_strafing_on_strafing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Strafing:Connect(function(active) + invokeFunction(callback_data, callback_vtable, active and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_strafing_on_strafing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Strafing:Connect(function(active) invokeFunction(callback_data, callback_vtable, active and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_swimming_on_swimming_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Swimming:Connect(function(speed) + invokeFunction(callback_data, callback_vtable, speed) + end)); + return createPointer(result_0); +end function abi.ffi.event_humanoid_swimming_on_swimming(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Swimming:Connect(function(speed) invokeFunction(callback_data, callback_vtable, speed) @@ -7891,6 +8642,12 @@ end function abi.ffi.method_lighting_set_minutes_after_midnight(self, minutes) getPointer(self):SetMinutesAfterMidnight(minutes) end +function abi.ffi.event_lighting_lighting_changed_on_lighting_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LightingChanged:Connect(function(sky_changed) + invokeFunction(callback_data, callback_vtable, sky_changed and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_lighting_lighting_changed_on_lighting_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LightingChanged:Connect(function(sky_changed) invokeFunction(callback_data, callback_vtable, sky_changed and 1 or 0) @@ -8023,6 +8780,17 @@ end function abi.ffi.property_setter_lod_data_entity_entity_lod_enabled_set_entity_lod_enabled(self, value) getPointer(self).EntityLodEnabled = value == 1; end +function abi.ffi.event_log_service_message_out_on_message_out_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageOut:Connect(function(message, message_type) + local message_len = #message; + local message_content = allocString(message_len); + for i = 1, message_len do + storeU8(memory, message_content + (i - 1), string.byte(message:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, message_content, message_len, message_type) + end)); + return createPointer(result_0); +end function abi.ffi.event_log_service_message_out_on_message_out(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageOut:Connect(function(message, message_type) local message_len = #message; @@ -8151,6 +8919,16 @@ function abi.ffi.method_marketplace_service_user_owns_game_pass_async(self, user end) return future; end +function abi.ffi.event_marketplace_service_prompt_bundle_purchase_finished_on_prompt_bundle_purchase_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptBundlePurchaseFinished:Connect(function(player, bundle_id, was_purchased) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, bundle_id, was_purchased and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_bundle_purchase_finished_on_prompt_bundle_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptBundlePurchaseFinished:Connect(function(player, bundle_id, was_purchased) local player_optional, player_optional_0 = 0, 0; @@ -8161,6 +8939,16 @@ function abi.ffi.event_marketplace_service_prompt_bundle_purchase_finished_on_pr end)); return createPointer(result_0); end +function abi.ffi.event_marketplace_service_prompt_game_pass_purchase_finished_on_prompt_game_pass_purchase_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptGamePassPurchaseFinished:Connect(function(player, game_pass_id, was_purchased) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, game_pass_id, was_purchased and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_game_pass_purchase_finished_on_prompt_game_pass_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptGamePassPurchaseFinished:Connect(function(player, game_pass_id, was_purchased) local player_optional, player_optional_0 = 0, 0; @@ -8171,12 +8959,28 @@ function abi.ffi.event_marketplace_service_prompt_game_pass_purchase_finished_on end)); return createPointer(result_0); end +function abi.ffi.event_marketplace_service_prompt_premium_purchase_finished_on_prompt_premium_purchase_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptPremiumPurchaseFinished:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_premium_purchase_finished_on_prompt_premium_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptPremiumPurchaseFinished:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_marketplace_service_prompt_purchase_finished_on_prompt_purchase_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptPurchaseFinished:Connect(function(player, asset_id, is_purchased) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, asset_id, is_purchased and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_purchase_finished_on_prompt_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptPurchaseFinished:Connect(function(player, asset_id, is_purchased) local player_optional, player_optional_0 = 0, 0; @@ -8187,6 +8991,16 @@ function abi.ffi.event_marketplace_service_prompt_purchase_finished_on_prompt_pu end)); return createPointer(result_0); end +function abi.ffi.event_marketplace_service_prompt_subscription_cancellation_finished_on_prompt_subscription_cancellation_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSubscriptionCancellationFinished:Connect(function(player, subscription_id, was_canceled) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, subscription_id, was_canceled and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_subscription_cancellation_finished_on_prompt_subscription_cancellation_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSubscriptionCancellationFinished:Connect(function(player, subscription_id, was_canceled) local player_optional, player_optional_0 = 0, 0; @@ -8197,6 +9011,16 @@ function abi.ffi.event_marketplace_service_prompt_subscription_cancellation_fini end)); return createPointer(result_0); end +function abi.ffi.event_marketplace_service_prompt_subscription_purchase_finished_on_prompt_subscription_purchase_finished_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSubscriptionPurchaseFinished:Connect(function(player, subscription_id, was_purchased) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, subscription_id, was_purchased and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_marketplace_service_prompt_subscription_purchase_finished_on_prompt_subscription_purchase_finished(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptSubscriptionPurchaseFinished:Connect(function(player, subscription_id, was_purchased) local player_optional, player_optional_0 = 0, 0; @@ -8328,54 +9152,108 @@ function abi.ffi.property_getter_mouse_y(self) local result_0 = getPointer(self).Y; return result_0; end +function abi.ffi.event_mouse_button_1_down_on_button_1_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button1Down:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_button_1_down_on_button_1_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button1Down:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_button_1_up_on_button_1_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button1Up:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_button_1_up_on_button_1_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button1Up:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_button_2_down_on_button_2_down_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button2Down:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_button_2_down_on_button_2_down(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button2Down:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_button_2_up_on_button_2_up_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button2Up:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_button_2_up_on_button_2_up(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Button2Up:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_idle_on_idle_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Idle:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_idle_on_idle(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Idle:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_move_on_move_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Move:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_move_on_move(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Move:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_wheel_backward_on_wheel_backward_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WheelBackward:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_wheel_backward_on_wheel_backward(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WheelBackward:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_mouse_wheel_forward_on_wheel_forward_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WheelForward:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_mouse_wheel_forward_on_wheel_forward(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WheelForward:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_network_marker_received_on_received_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Received:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_network_marker_received_on_received(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Received:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -8753,7 +9631,17 @@ end function abi.ffi.method_base_part_set_network_ownership_auto(self) getPointer(self):SetNetworkOwnershipAuto() end -function abi.ffi.event_base_part_touch_ended_on_touch_ended(self, callback_data, callback_vtable) +function abi.ffi.event_base_part_touch_ended_on_touch_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchEnded:Connect(function(other_part) + local other_part_optional, other_part_optional_0 = 0, 0; + if (other_part ~= nil) then + other_part_optional, other_part_optional_0 = 1, createPointer(other_part); + end + invokeFunction(callback_data, callback_vtable, other_part_optional, other_part_optional_0) + end)); + return createPointer(result_0); +end +function abi.ffi.event_base_part_touch_ended_on_touch_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchEnded:Connect(function(other_part) local other_part_optional, other_part_optional_0 = 0, 0; if (other_part ~= nil) then @@ -9251,6 +10139,16 @@ function abi.ffi.method_workspace_pgs_is_enabled(self) local result_0 = getPointer(self):PGSIsEnabled(); return result_0 and 1 or 0; end +function abi.ffi.event_workspace_persistent_loaded_on_persistent_loaded_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PersistentLoaded:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_workspace_persistent_loaded_on_persistent_loaded(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PersistentLoaded:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -9550,12 +10448,24 @@ end function abi.ffi.method_path_compute_async(self, start, finish) getPointer(self):ComputeAsync(getPointer(start), getPointer(finish)) end +function abi.ffi.event_path_blocked_on_blocked_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Blocked:Connect(function(blocked_waypoint_idx) + invokeFunction(callback_data, callback_vtable, blocked_waypoint_idx) + end)); + return createPointer(result_0); +end function abi.ffi.event_path_blocked_on_blocked(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Blocked:Connect(function(blocked_waypoint_idx) invokeFunction(callback_data, callback_vtable, blocked_waypoint_idx) end)); return createPointer(result_0); end +function abi.ffi.event_path_unblocked_on_unblocked_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Unblocked:Connect(function(unblocked_waypoint_idx) + invokeFunction(callback_data, callback_vtable, unblocked_waypoint_idx) + end)); + return createPointer(result_0); +end function abi.ffi.event_path_unblocked_on_unblocked(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Unblocked:Connect(function(unblocked_waypoint_idx) invokeFunction(callback_data, callback_vtable, unblocked_waypoint_idx) @@ -9980,6 +10890,16 @@ end function abi.ffi.method_player_request_stream_around_async(self, position, time_out) getPointer(self):RequestStreamAroundAsync(getPointer(position), time_out) end +function abi.ffi.event_player_character_added_on_character_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterAdded:Connect(function(character) + local character_optional, character_optional_0 = 0, 0; + if (character ~= nil) then + character_optional, character_optional_0 = 1, createPointer(character); + end + invokeFunction(callback_data, callback_vtable, character_optional, character_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_character_added_on_character_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterAdded:Connect(function(character) local character_optional, character_optional_0 = 0, 0; @@ -9990,6 +10910,16 @@ function abi.ffi.event_player_character_added_on_character_added(self, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_player_character_appearance_loaded_on_character_appearance_loaded_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterAppearanceLoaded:Connect(function(character) + local character_optional, character_optional_0 = 0, 0; + if (character ~= nil) then + character_optional, character_optional_0 = 1, createPointer(character); + end + invokeFunction(callback_data, callback_vtable, character_optional, character_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_character_appearance_loaded_on_character_appearance_loaded(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterAppearanceLoaded:Connect(function(character) local character_optional, character_optional_0 = 0, 0; @@ -10000,6 +10930,16 @@ function abi.ffi.event_player_character_appearance_loaded_on_character_appearanc end)); return createPointer(result_0); end +function abi.ffi.event_player_character_removing_on_character_removing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterRemoving:Connect(function(character) + local character_optional, character_optional_0 = 0, 0; + if (character ~= nil) then + character_optional, character_optional_0 = 1, createPointer(character); + end + invokeFunction(callback_data, callback_vtable, character_optional, character_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_character_removing_on_character_removing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).CharacterRemoving:Connect(function(character) local character_optional, character_optional_0 = 0, 0; @@ -10010,6 +10950,21 @@ function abi.ffi.event_player_character_removing_on_character_removing(self, cal end)); return createPointer(result_0); end +function abi.ffi.event_player_chatted_on_chatted_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Chatted:Connect(function(message, recipient) + local message_len = #message; + local message_content = allocString(message_len); + for i = 1, message_len do + storeU8(memory, message_content + (i - 1), string.byte(message:sub(i, i))); + end + local recipient_optional, recipient_optional_0 = 0, 0; + if (recipient ~= nil) then + recipient_optional, recipient_optional_0 = 1, createPointer(recipient); + end + invokeFunction(callback_data, callback_vtable, message_content, message_len, recipient_optional, recipient_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_chatted_on_chatted(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Chatted:Connect(function(message, recipient) local message_len = #message; @@ -10025,12 +10980,29 @@ function abi.ffi.event_player_chatted_on_chatted(self, callback_data, callback_v end)); return createPointer(result_0); end +function abi.ffi.event_player_idled_on_idled_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Idled:Connect(function(time) + invokeFunction(callback_data, callback_vtable, time) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_idled_on_idled(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Idled:Connect(function(time) invokeFunction(callback_data, callback_vtable, time) end)); return createPointer(result_0); end +function abi.ffi.event_player_on_teleport_on_on_teleport_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).OnTeleport:Connect(function(teleport_state, place_id, spawn_name) + local spawn_name_len = #spawn_name; + local spawn_name_content = allocString(spawn_name_len); + for i = 1, spawn_name_len do + storeU8(memory, spawn_name_content + (i - 1), string.byte(spawn_name:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, teleport_state, place_id, spawn_name_content, spawn_name_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_player_on_teleport_on_on_teleport(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).OnTeleport:Connect(function(teleport_state, place_id, spawn_name) local spawn_name_len = #spawn_name; @@ -10228,6 +11200,16 @@ function abi.ffi.method_players_get_user_id_from_name_async(self, user_name_addr end) return future; end +function abi.ffi.event_players_player_added_on_player_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerAdded:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_players_player_added_on_player_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerAdded:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -10238,6 +11220,16 @@ function abi.ffi.event_players_player_added_on_player_added(self, callback_data, end)); return createPointer(result_0); end +function abi.ffi.event_players_player_membership_changed_on_player_membership_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerMembershipChanged:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_players_player_membership_changed_on_player_membership_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerMembershipChanged:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -10248,6 +11240,16 @@ function abi.ffi.event_players_player_membership_changed_on_player_membership_ch end)); return createPointer(result_0); end +function abi.ffi.event_players_player_removing_on_player_removing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerRemoving:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_players_player_removing_on_player_removing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerRemoving:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -10522,6 +11524,16 @@ end function abi.ffi.method_proximity_prompt_input_hold_end(self) getPointer(self):InputHoldEnd() end +function abi.ffi.event_proximity_prompt_prompt_button_hold_began_on_prompt_button_hold_began_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldBegan:Connect(function(player_who_triggered) + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_prompt_button_hold_began_on_prompt_button_hold_began(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldBegan:Connect(function(player_who_triggered) local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; @@ -10532,6 +11544,16 @@ function abi.ffi.event_proximity_prompt_prompt_button_hold_began_on_prompt_butto end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_prompt_button_hold_ended_on_prompt_button_hold_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldEnded:Connect(function(player_who_triggered) + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_prompt_button_hold_ended_on_prompt_button_hold_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldEnded:Connect(function(player_who_triggered) local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; @@ -10542,18 +11564,40 @@ function abi.ffi.event_proximity_prompt_prompt_button_hold_ended_on_prompt_butto end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_prompt_hidden_on_prompt_hidden_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptHidden:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_prompt_hidden_on_prompt_hidden(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptHidden:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_prompt_shown_on_prompt_shown_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptShown:Connect(function(input_type) + invokeFunction(callback_data, callback_vtable, input_type) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_prompt_shown_on_prompt_shown(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptShown:Connect(function(input_type) invokeFunction(callback_data, callback_vtable, input_type) end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_trigger_ended_on_trigger_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TriggerEnded:Connect(function(player_who_triggered) + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_trigger_ended_on_trigger_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TriggerEnded:Connect(function(player_who_triggered) local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; @@ -10564,6 +11608,16 @@ function abi.ffi.event_proximity_prompt_trigger_ended_on_trigger_ended(self, cal end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_triggered_on_triggered_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Triggered:Connect(function(player_who_triggered) + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_triggered_on_triggered(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Triggered:Connect(function(player_who_triggered) local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; @@ -10588,6 +11642,20 @@ end function abi.ffi.property_setter_proximity_prompt_service_max_prompts_visible_set_max_prompts_visible(self, value) getPointer(self).MaxPromptsVisible = value; end +function abi.ffi.event_proximity_prompt_service_prompt_button_hold_began_on_prompt_button_hold_began_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldBegan:Connect(function(prompt, player_who_triggered) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_button_hold_began_on_prompt_button_hold_began(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldBegan:Connect(function(prompt, player_who_triggered) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10602,6 +11670,20 @@ function abi.ffi.event_proximity_prompt_service_prompt_button_hold_began_on_prom end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_service_prompt_button_hold_ended_on_prompt_button_hold_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldEnded:Connect(function(prompt, player_who_triggered) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_button_hold_ended_on_prompt_button_hold_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptButtonHoldEnded:Connect(function(prompt, player_who_triggered) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10616,6 +11698,16 @@ function abi.ffi.event_proximity_prompt_service_prompt_button_hold_ended_on_prom end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_service_prompt_hidden_on_prompt_hidden_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptHidden:Connect(function(prompt) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_hidden_on_prompt_hidden(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptHidden:Connect(function(prompt) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10626,6 +11718,16 @@ function abi.ffi.event_proximity_prompt_service_prompt_hidden_on_prompt_hidden(s end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_service_prompt_shown_on_prompt_shown_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptShown:Connect(function(prompt, input_type) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0, input_type) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_shown_on_prompt_shown(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptShown:Connect(function(prompt, input_type) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10636,6 +11738,20 @@ function abi.ffi.event_proximity_prompt_service_prompt_shown_on_prompt_shown(sel end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_service_prompt_trigger_ended_on_prompt_trigger_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptTriggerEnded:Connect(function(prompt, player_who_triggered) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_trigger_ended_on_prompt_trigger_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptTriggerEnded:Connect(function(prompt, player_who_triggered) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10650,6 +11766,20 @@ function abi.ffi.event_proximity_prompt_service_prompt_trigger_ended_on_prompt_t end)); return createPointer(result_0); end +function abi.ffi.event_proximity_prompt_service_prompt_triggered_on_prompt_triggered_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptTriggered:Connect(function(prompt, player_who_triggered) + local prompt_optional, prompt_optional_0 = 0, 0; + if (prompt ~= nil) then + prompt_optional, prompt_optional_0 = 1, createPointer(prompt); + end + local player_who_triggered_optional, player_who_triggered_optional_0 = 0, 0; + if (player_who_triggered ~= nil) then + player_who_triggered_optional, player_who_triggered_optional_0 = 1, createPointer(player_who_triggered); + end + invokeFunction(callback_data, callback_vtable, prompt_optional, prompt_optional_0, player_who_triggered_optional, player_who_triggered_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_proximity_prompt_service_prompt_triggered_on_prompt_triggered(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PromptTriggered:Connect(function(prompt, player_who_triggered) local prompt_optional, prompt_optional_0 = 0, 0; @@ -10826,44 +11956,86 @@ end function abi.ffi.method_run_service_unbind_from_render_step(self, name_addr, name_len) getPointer(self):UnbindFromRenderStep(loadString(memory, name_addr, name_len)) end +function abi.ffi.event_run_service_heartbeat_on_heartbeat_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Heartbeat:Connect(function(delta_time) + invokeFunction(callback_data, callback_vtable, delta_time) + end)); + return createPointer(result_0); +end function abi.ffi.event_run_service_heartbeat_on_heartbeat(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Heartbeat:Connect(function(delta_time) invokeFunction(callback_data, callback_vtable, delta_time) end)); return createPointer(result_0); end +function abi.ffi.event_run_service_post_simulation_on_post_simulation_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PostSimulation:Connect(function(delta_time_sim) + invokeFunction(callback_data, callback_vtable, delta_time_sim) + end)); + return createPointer(result_0); +end function abi.ffi.event_run_service_post_simulation_on_post_simulation(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PostSimulation:Connect(function(delta_time_sim) invokeFunction(callback_data, callback_vtable, delta_time_sim) end)); return createPointer(result_0); end +function abi.ffi.event_run_service_pre_animation_on_pre_animation_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreAnimation:Connect(function(delta_time_sim) + invokeFunction(callback_data, callback_vtable, delta_time_sim) + end)); + return createPointer(result_0); +end function abi.ffi.event_run_service_pre_animation_on_pre_animation(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreAnimation:Connect(function(delta_time_sim) invokeFunction(callback_data, callback_vtable, delta_time_sim) end)); return createPointer(result_0); end +function abi.ffi.event_run_service_pre_render_on_pre_render_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreRender:Connect(function(delta_time_render) + invokeFunction(callback_data, callback_vtable, delta_time_render) + end)); + return createPointer(result_0); +end function abi.ffi.event_run_service_pre_render_on_pre_render(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreRender:Connect(function(delta_time_render) invokeFunction(callback_data, callback_vtable, delta_time_render) end)); return createPointer(result_0); end +function abi.ffi.event_run_service_pre_simulation_on_pre_simulation_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreSimulation:Connect(function(delta_time_sim) + invokeFunction(callback_data, callback_vtable, delta_time_sim) + end)); + return createPointer(result_0); +end function abi.ffi.event_run_service_pre_simulation_on_pre_simulation(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PreSimulation:Connect(function(delta_time_sim) invokeFunction(callback_data, callback_vtable, delta_time_sim) end)); return createPointer(result_0); end -function abi.ffi.event_run_service_render_stepped_on_render_stepped(self, callback_data, callback_vtable) +function abi.ffi.event_run_service_render_stepped_on_render_stepped_async(self, callback_data, callback_vtable, callback_poll) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).RenderStepped:Connect(function(delta_time) invokeFunction(callback_data, callback_vtable, delta_time) end)); return createPointer(result_0); end -function abi.ffi.event_run_service_stepped_on_stepped(self, callback_data, callback_vtable) - local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stepped:Connect(function(time, delta_time) +function abi.ffi.event_run_service_render_stepped_on_render_stepped(self, callback_data, callback_vtable) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).RenderStepped:Connect(function(delta_time) + invokeFunction(callback_data, callback_vtable, delta_time) + end)); + return createPointer(result_0); +end +function abi.ffi.event_run_service_stepped_on_stepped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stepped:Connect(function(time, delta_time) + invokeFunction(callback_data, callback_vtable, time, delta_time) + end)); + return createPointer(result_0); +end +function abi.ffi.event_run_service_stepped_on_stepped(self, callback_data, callback_vtable) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stepped:Connect(function(time, delta_time) invokeFunction(callback_data, callback_vtable, time, delta_time) end)); return createPointer(result_0); @@ -10924,6 +12096,26 @@ end function abi.ffi.property_setter_screenshot_hud_visible_set_visible(self, value) getPointer(self).Visible = value == 1; end +function abi.ffi.event_script_context_error_on_error_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Error:Connect(function(message, stack_trace, script) + local message_len = #message; + local message_content = allocString(message_len); + for i = 1, message_len do + storeU8(memory, message_content + (i - 1), string.byte(message:sub(i, i))); + end + local stack_trace_len = #stack_trace; + local stack_trace_content = allocString(stack_trace_len); + for i = 1, stack_trace_len do + storeU8(memory, stack_trace_content + (i - 1), string.byte(stack_trace:sub(i, i))); + end + local script_optional, script_optional_0 = 0, 0; + if (script ~= nil) then + script_optional, script_optional_0 = 1, createPointer(script); + end + invokeFunction(callback_data, callback_vtable, message_content, message_len, stack_trace_content, stack_trace_len, script_optional, script_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_script_context_error_on_error(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Error:Connect(function(message, stack_trace, script) local message_len = #message; @@ -10960,12 +12152,28 @@ function abi.ffi.method_service_provider_get_service(self, class_name_addr, clas end return result_0_optional, result_0_optional_0; end +function abi.ffi.event_service_provider_close_on_close_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Close:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_service_provider_close_on_close(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Close:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_service_provider_service_added_on_service_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ServiceAdded:Connect(function(service) + local service_optional, service_optional_0 = 0, 0; + if (service ~= nil) then + service_optional, service_optional_0 = 1, createPointer(service); + end + invokeFunction(callback_data, callback_vtable, service_optional, service_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_service_provider_service_added_on_service_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ServiceAdded:Connect(function(service) local service_optional, service_optional_0 = 0, 0; @@ -10976,6 +12184,16 @@ function abi.ffi.event_service_provider_service_added_on_service_added(self, cal end)); return createPointer(result_0); end +function abi.ffi.event_service_provider_service_removing_on_service_removing_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ServiceRemoving:Connect(function(service) + local service_optional, service_optional_0 = 0, 0; + if (service ~= nil) then + service_optional, service_optional_0 = 1, createPointer(service); + end + invokeFunction(callback_data, callback_vtable, service_optional, service_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_service_provider_service_removing_on_service_removing(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).ServiceRemoving:Connect(function(service) local service_optional, service_optional_0 = 0, 0; @@ -11044,12 +12262,24 @@ function abi.ffi.method_data_model_is_loaded(self) local result_0 = getPointer(self):IsLoaded(); return result_0 and 1 or 0; end +function abi.ffi.event_data_model_graphics_quality_change_request_on_graphics_quality_change_request_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GraphicsQualityChangeRequest:Connect(function(better_quality) + invokeFunction(callback_data, callback_vtable, better_quality and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_data_model_graphics_quality_change_request_on_graphics_quality_change_request(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GraphicsQualityChangeRequest:Connect(function(better_quality) invokeFunction(callback_data, callback_vtable, better_quality and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_data_model_loaded_on_loaded_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_data_model_loaded_on_loaded(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -11337,6 +12567,17 @@ end function abi.ffi.method_sound_stop(self) getPointer(self):Stop() end +function abi.ffi.event_sound_did_loop_on_did_loop_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function(sound_id, num_of_times_looped) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len, num_of_times_looped) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_did_loop_on_did_loop(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DidLoop:Connect(function(sound_id, num_of_times_looped) local sound_id_len = #sound_id; @@ -11348,6 +12589,17 @@ function abi.ffi.event_sound_did_loop_on_did_loop(self, callback_data, callback_ end)); return createPointer(result_0); end +function abi.ffi.event_sound_ended_on_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ended:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_ended_on_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Ended:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11359,6 +12611,17 @@ function abi.ffi.event_sound_ended_on_ended(self, callback_data, callback_vtable end)); return createPointer(result_0); end +function abi.ffi.event_sound_loaded_on_loaded_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_loaded_on_loaded(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Loaded:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11370,6 +12633,17 @@ function abi.ffi.event_sound_loaded_on_loaded(self, callback_data, callback_vtab end)); return createPointer(result_0); end +function abi.ffi.event_sound_paused_on_paused_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Paused:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_paused_on_paused(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Paused:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11381,6 +12655,17 @@ function abi.ffi.event_sound_paused_on_paused(self, callback_data, callback_vtab end)); return createPointer(result_0); end +function abi.ffi.event_sound_played_on_played_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Played:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_played_on_played(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Played:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11392,6 +12677,17 @@ function abi.ffi.event_sound_played_on_played(self, callback_data, callback_vtab end)); return createPointer(result_0); end +function abi.ffi.event_sound_resumed_on_resumed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Resumed:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_resumed_on_resumed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Resumed:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11403,6 +12699,17 @@ function abi.ffi.event_sound_resumed_on_resumed(self, callback_data, callback_vt end)); return createPointer(result_0); end +function abi.ffi.event_sound_stopped_on_stopped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function(sound_id) + local sound_id_len = #sound_id; + local sound_id_content = allocString(sound_id_len); + for i = 1, sound_id_len do + storeU8(memory, sound_id_content + (i - 1), string.byte(sound_id:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, sound_id_content, sound_id_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_sound_stopped_on_stopped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function(sound_id) local sound_id_len = #sound_id; @@ -11982,6 +13289,16 @@ end function abi.ffi.property_setter_team_team_color_set_team_color(self, value) getPointer(self).TeamColor = getPointer(value); end +function abi.ffi.event_team_player_added_on_player_added_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerAdded:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_team_player_added_on_player_added(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerAdded:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -11992,6 +13309,16 @@ function abi.ffi.event_team_player_added_on_player_added(self, callback_data, ca end)); return createPointer(result_0); end +function abi.ffi.event_team_player_removed_on_player_removed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerRemoved:Connect(function(player) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_team_player_removed_on_player_removed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PlayerRemoved:Connect(function(player) local player_optional, player_optional_0 = 0, 0; @@ -12062,6 +13389,25 @@ end function abi.ffi.method_teleport_service_set_teleport_gui(self, gui) getPointer(self):SetTeleportGui(getPointer(gui)) end +function abi.ffi.event_teleport_service_teleport_init_failed_on_teleport_init_failed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TeleportInitFailed:Connect(function(player, teleport_result, error_message, place_id, teleport_options) + local player_optional, player_optional_0 = 0, 0; + if (player ~= nil) then + player_optional, player_optional_0 = 1, createPointer(player); + end + local error_message_len = #error_message; + local error_message_content = allocString(error_message_len); + for i = 1, error_message_len do + storeU8(memory, error_message_content + (i - 1), string.byte(error_message:sub(i, i))); + end + local teleport_options_optional, teleport_options_optional_0 = 0, 0; + if (teleport_options ~= nil) then + teleport_options_optional, teleport_options_optional_0 = 1, createPointer(teleport_options); + end + invokeFunction(callback_data, callback_vtable, player_optional, player_optional_0, teleport_result, error_message_content, error_message_len, place_id, teleport_options_optional, teleport_options_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_teleport_service_teleport_init_failed_on_teleport_init_failed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TeleportInitFailed:Connect(function(player, teleport_result, error_message, place_id, teleport_options) local player_optional, player_optional_0 = 0, 0; @@ -12130,6 +13476,16 @@ function abi.ffi.method_text_channel_send_async(self, message_addr, message_len, end) return future; end +function abi.ffi.event_text_channel_message_received_on_message_received_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageReceived:Connect(function(incoming_message) + local incoming_message_optional, incoming_message_optional_0 = 0, 0; + if (incoming_message ~= nil) then + incoming_message_optional, incoming_message_optional_0 = 1, createPointer(incoming_message); + end + invokeFunction(callback_data, callback_vtable, incoming_message_optional, incoming_message_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_channel_message_received_on_message_received(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageReceived:Connect(function(incoming_message) local incoming_message_optional, incoming_message_optional_0 = 0, 0; @@ -12171,6 +13527,21 @@ end function abi.ffi.property_setter_text_chat_command_secondary_alias_set_secondary_alias(self, value_addr, value_len) getPointer(self).SecondaryAlias = loadString(memory, value_addr, value_len); end +function abi.ffi.event_text_chat_command_triggered_on_triggered_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Triggered:Connect(function(origin_text_source, unfiltered_text) + local origin_text_source_optional, origin_text_source_optional_0 = 0, 0; + if (origin_text_source ~= nil) then + origin_text_source_optional, origin_text_source_optional_0 = 1, createPointer(origin_text_source); + end + local unfiltered_text_len = #unfiltered_text; + local unfiltered_text_content = allocString(unfiltered_text_len); + for i = 1, unfiltered_text_len do + storeU8(memory, unfiltered_text_content + (i - 1), string.byte(unfiltered_text:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, origin_text_source_optional, origin_text_source_optional_0, unfiltered_text_content, unfiltered_text_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_chat_command_triggered_on_triggered(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Triggered:Connect(function(origin_text_source, unfiltered_text) local origin_text_source_optional, origin_text_source_optional_0 = 0, 0; @@ -12459,6 +13830,16 @@ end function abi.ffi.property_setter_text_chat_service_create_default_text_channels_set_create_default_text_channels(self, value) getPointer(self).CreateDefaultTextChannels = value == 1; end +function abi.ffi.event_text_chat_service_message_received_on_message_received_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageReceived:Connect(function(text_chat_message) + local text_chat_message_optional, text_chat_message_optional_0 = 0, 0; + if (text_chat_message ~= nil) then + text_chat_message_optional, text_chat_message_optional_0 = 1, createPointer(text_chat_message); + end + invokeFunction(callback_data, callback_vtable, text_chat_message_optional, text_chat_message_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_chat_service_message_received_on_message_received(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).MessageReceived:Connect(function(text_chat_message) local text_chat_message_optional, text_chat_message_optional_0 = 0, 0; @@ -12469,6 +13850,16 @@ function abi.ffi.event_text_chat_service_message_received_on_message_received(se end)); return createPointer(result_0); end +function abi.ffi.event_text_chat_service_sending_message_on_sending_message_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SendingMessage:Connect(function(text_chat_message) + local text_chat_message_optional, text_chat_message_optional_0 = 0, 0; + if (text_chat_message ~= nil) then + text_chat_message_optional, text_chat_message_optional_0 = 1, createPointer(text_chat_message); + end + invokeFunction(callback_data, callback_vtable, text_chat_message_optional, text_chat_message_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_text_chat_service_sending_message_on_sending_message(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).SendingMessage:Connect(function(text_chat_message) local text_chat_message_optional, text_chat_message_optional_0 = 0, 0; @@ -12754,6 +14145,12 @@ end function abi.ffi.method_tween_base_play(self) getPointer(self):Play() end +function abi.ffi.event_tween_base_completed_on_completed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Completed:Connect(function(playback_state) + invokeFunction(callback_data, callback_vtable, playback_state) + end)); + return createPointer(result_0); +end function abi.ffi.event_tween_base_completed_on_completed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Completed:Connect(function(playback_state) invokeFunction(callback_data, callback_vtable, playback_state) @@ -13025,6 +14422,16 @@ end function abi.ffi.method_ui_page_layout_previous(self) getPointer(self):Previous() end +function abi.ffi.event_ui_page_layout_page_enter_on_page_enter_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PageEnter:Connect(function(page) + local page_optional, page_optional_0 = 0, 0; + if (page ~= nil) then + page_optional, page_optional_0 = 1, createPointer(page); + end + invokeFunction(callback_data, callback_vtable, page_optional, page_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_ui_page_layout_page_enter_on_page_enter(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PageEnter:Connect(function(page) local page_optional, page_optional_0 = 0, 0; @@ -13035,6 +14442,16 @@ function abi.ffi.event_ui_page_layout_page_enter_on_page_enter(self, callback_da end)); return createPointer(result_0); end +function abi.ffi.event_ui_page_layout_page_leave_on_page_leave_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PageLeave:Connect(function(page) + local page_optional, page_optional_0 = 0, 0; + if (page ~= nil) then + page_optional, page_optional_0 = 1, createPointer(page); + end + invokeFunction(callback_data, callback_vtable, page_optional, page_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_ui_page_layout_page_leave_on_page_leave(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PageLeave:Connect(function(page) local page_optional, page_optional_0 = 0, 0; @@ -13045,6 +14462,16 @@ function abi.ffi.event_ui_page_layout_page_leave_on_page_leave(self, callback_da end)); return createPointer(result_0); end +function abi.ffi.event_ui_page_layout_stopped_on_stopped_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function(current_page) + local current_page_optional, current_page_optional_0 = 0, 0; + if (current_page ~= nil) then + current_page_optional, current_page_optional_0 = 1, createPointer(current_page); + end + invokeFunction(callback_data, callback_vtable, current_page_optional, current_page_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_ui_page_layout_stopped_on_stopped(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Stopped:Connect(function(current_page) local current_page_optional, current_page_optional_0 = 0, 0; @@ -13276,12 +14703,24 @@ end function abi.ffi.method_user_game_settings_set_onboarding_completed(self, onboarding_id_addr, onboarding_id_len) getPointer(self):SetOnboardingCompleted(loadString(memory, onboarding_id_addr, onboarding_id_len)) end +function abi.ffi.event_user_game_settings_fullscreen_changed_on_fullscreen_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FullscreenChanged:Connect(function(is_fullscreen) + invokeFunction(callback_data, callback_vtable, is_fullscreen and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_game_settings_fullscreen_changed_on_fullscreen_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).FullscreenChanged:Connect(function(is_fullscreen) invokeFunction(callback_data, callback_vtable, is_fullscreen and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_user_game_settings_studio_mode_changed_on_studio_mode_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StudioModeChanged:Connect(function(is_studio_mode) + invokeFunction(callback_data, callback_vtable, is_studio_mode and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_game_settings_studio_mode_changed_on_studio_mode_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).StudioModeChanged:Connect(function(is_studio_mode) invokeFunction(callback_data, callback_vtable, is_studio_mode and 1 or 0) @@ -13428,6 +14867,16 @@ end function abi.ffi.method_user_input_service_set_navigation_gamepad(self, gamepad_enum, enabled) getPointer(self):SetNavigationGamepad(gamepad_enum, enabled == 1) end +function abi.ffi.event_user_input_service_device_acceleration_changed_on_device_acceleration_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceAccelerationChanged:Connect(function(acceleration) + local acceleration_optional, acceleration_optional_0 = 0, 0; + if (acceleration ~= nil) then + acceleration_optional, acceleration_optional_0 = 1, createPointer(acceleration); + end + invokeFunction(callback_data, callback_vtable, acceleration_optional, acceleration_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_device_acceleration_changed_on_device_acceleration_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceAccelerationChanged:Connect(function(acceleration) local acceleration_optional, acceleration_optional_0 = 0, 0; @@ -13438,6 +14887,16 @@ function abi.ffi.event_user_input_service_device_acceleration_changed_on_device_ end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_device_gravity_changed_on_device_gravity_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceGravityChanged:Connect(function(gravity) + local gravity_optional, gravity_optional_0 = 0, 0; + if (gravity ~= nil) then + gravity_optional, gravity_optional_0 = 1, createPointer(gravity); + end + invokeFunction(callback_data, callback_vtable, gravity_optional, gravity_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_device_gravity_changed_on_device_gravity_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceGravityChanged:Connect(function(gravity) local gravity_optional, gravity_optional_0 = 0, 0; @@ -13448,6 +14907,16 @@ function abi.ffi.event_user_input_service_device_gravity_changed_on_device_gravi end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_device_rotation_changed_on_device_rotation_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceRotationChanged:Connect(function(rotation, cframe) + local rotation_optional, rotation_optional_0 = 0, 0; + if (rotation ~= nil) then + rotation_optional, rotation_optional_0 = 1, createPointer(rotation); + end + invokeFunction(callback_data, callback_vtable, rotation_optional, rotation_optional_0, createPointer(cframe)) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_device_rotation_changed_on_device_rotation_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).DeviceRotationChanged:Connect(function(rotation, cframe) local rotation_optional, rotation_optional_0 = 0, 0; @@ -13458,18 +14927,40 @@ function abi.ffi.event_user_input_service_device_rotation_changed_on_device_rota end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_gamepad_connected_on_gamepad_connected_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GamepadConnected:Connect(function(gamepad_num) + invokeFunction(callback_data, callback_vtable, gamepad_num) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_gamepad_connected_on_gamepad_connected(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GamepadConnected:Connect(function(gamepad_num) invokeFunction(callback_data, callback_vtable, gamepad_num) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_gamepad_disconnected_on_gamepad_disconnected_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GamepadDisconnected:Connect(function(gamepad_num) + invokeFunction(callback_data, callback_vtable, gamepad_num) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_gamepad_disconnected_on_gamepad_disconnected(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).GamepadDisconnected:Connect(function(gamepad_num) invokeFunction(callback_data, callback_vtable, gamepad_num) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_input_began_on_input_began_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputBegan:Connect(function(input, game_processed_event) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_input_began_on_input_began(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputBegan:Connect(function(input, game_processed_event) local input_optional, input_optional_0 = 0, 0; @@ -13480,6 +14971,16 @@ function abi.ffi.event_user_input_service_input_began_on_input_began(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_input_changed_on_input_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputChanged:Connect(function(input, game_processed_event) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_input_changed_on_input_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputChanged:Connect(function(input, game_processed_event) local input_optional, input_optional_0 = 0, 0; @@ -13490,6 +14991,16 @@ function abi.ffi.event_user_input_service_input_changed_on_input_changed(self, c end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_input_ended_on_input_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputEnded:Connect(function(input, game_processed_event) + local input_optional, input_optional_0 = 0, 0; + if (input ~= nil) then + input_optional, input_optional_0 = 1, createPointer(input); + end + invokeFunction(callback_data, callback_vtable, input_optional, input_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_input_ended_on_input_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).InputEnded:Connect(function(input, game_processed_event) local input_optional, input_optional_0 = 0, 0; @@ -13500,24 +15011,52 @@ function abi.ffi.event_user_input_service_input_ended_on_input_ended(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_jump_request_on_jump_request_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).JumpRequest:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_jump_request_on_jump_request(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).JumpRequest:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_last_input_type_changed_on_last_input_type_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LastInputTypeChanged:Connect(function(last_input_type) + invokeFunction(callback_data, callback_vtable, last_input_type) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_last_input_type_changed_on_last_input_type_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).LastInputTypeChanged:Connect(function(last_input_type) invokeFunction(callback_data, callback_vtable, last_input_type) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_pointer_action_on_pointer_action_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PointerAction:Connect(function(wheel, pan, pinch, game_processed_event) + invokeFunction(callback_data, callback_vtable, wheel, createPointer(pan), pinch, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_pointer_action_on_pointer_action(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).PointerAction:Connect(function(wheel, pan, pinch, game_processed_event) invokeFunction(callback_data, callback_vtable, wheel, createPointer(pan), pinch, game_processed_event and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_text_box_focus_released_on_text_box_focus_released_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TextBoxFocusReleased:Connect(function(textbox_released) + local textbox_released_optional, textbox_released_optional_0 = 0, 0; + if (textbox_released ~= nil) then + textbox_released_optional, textbox_released_optional_0 = 1, createPointer(textbox_released); + end + invokeFunction(callback_data, callback_vtable, textbox_released_optional, textbox_released_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_text_box_focus_released_on_text_box_focus_released(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TextBoxFocusReleased:Connect(function(textbox_released) local textbox_released_optional, textbox_released_optional_0 = 0, 0; @@ -13528,6 +15067,16 @@ function abi.ffi.event_user_input_service_text_box_focus_released_on_text_box_fo end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_text_box_focused_on_text_box_focused_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TextBoxFocused:Connect(function(textbox_focused) + local textbox_focused_optional, textbox_focused_optional_0 = 0, 0; + if (textbox_focused ~= nil) then + textbox_focused_optional, textbox_focused_optional_0 = 1, createPointer(textbox_focused); + end + invokeFunction(callback_data, callback_vtable, textbox_focused_optional, textbox_focused_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_text_box_focused_on_text_box_focused(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TextBoxFocused:Connect(function(textbox_focused) local textbox_focused_optional, textbox_focused_optional_0 = 0, 0; @@ -13538,6 +15087,16 @@ function abi.ffi.event_user_input_service_text_box_focused_on_text_box_focused(s end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_touch_ended_on_touch_ended_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchEnded:Connect(function(touch, game_processed_event) + local touch_optional, touch_optional_0 = 0, 0; + if (touch ~= nil) then + touch_optional, touch_optional_0 = 1, createPointer(touch); + end + invokeFunction(callback_data, callback_vtable, touch_optional, touch_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_touch_ended_on_touch_ended(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchEnded:Connect(function(touch, game_processed_event) local touch_optional, touch_optional_0 = 0, 0; @@ -13548,6 +15107,16 @@ function abi.ffi.event_user_input_service_touch_ended_on_touch_ended(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_touch_moved_on_touch_moved_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchMoved:Connect(function(touch, game_processed_event) + local touch_optional, touch_optional_0 = 0, 0; + if (touch ~= nil) then + touch_optional, touch_optional_0 = 1, createPointer(touch); + end + invokeFunction(callback_data, callback_vtable, touch_optional, touch_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_touch_moved_on_touch_moved(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchMoved:Connect(function(touch, game_processed_event) local touch_optional, touch_optional_0 = 0, 0; @@ -13558,6 +15127,16 @@ function abi.ffi.event_user_input_service_touch_moved_on_touch_moved(self, callb end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_touch_started_on_touch_started_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchStarted:Connect(function(touch, game_processed_event) + local touch_optional, touch_optional_0 = 0, 0; + if (touch ~= nil) then + touch_optional, touch_optional_0 = 1, createPointer(touch); + end + invokeFunction(callback_data, callback_vtable, touch_optional, touch_optional_0, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_touch_started_on_touch_started(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchStarted:Connect(function(touch, game_processed_event) local touch_optional, touch_optional_0 = 0, 0; @@ -13568,30 +15147,60 @@ function abi.ffi.event_user_input_service_touch_started_on_touch_started(self, c end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_touch_swipe_on_touch_swipe_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchSwipe:Connect(function(swipe_direction, number_of_touches, game_processed_event) + invokeFunction(callback_data, callback_vtable, swipe_direction, number_of_touches, game_processed_event and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_touch_swipe_on_touch_swipe(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchSwipe:Connect(function(swipe_direction, number_of_touches, game_processed_event) invokeFunction(callback_data, callback_vtable, swipe_direction, number_of_touches, game_processed_event and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_touch_tap_in_world_on_touch_tap_in_world_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchTapInWorld:Connect(function(position, processed_by_ui) + invokeFunction(callback_data, callback_vtable, createPointer(position), processed_by_ui and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_touch_tap_in_world_on_touch_tap_in_world(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchTapInWorld:Connect(function(position, processed_by_ui) invokeFunction(callback_data, callback_vtable, createPointer(position), processed_by_ui and 1 or 0) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_user_c_frame_changed_on_user_c_frame_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameChanged:Connect(function(type, value) + invokeFunction(callback_data, callback_vtable, type, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_user_c_frame_changed_on_user_c_frame_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameChanged:Connect(function(type, value) invokeFunction(callback_data, callback_vtable, type, createPointer(value)) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_window_focus_released_on_window_focus_released_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WindowFocusReleased:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_window_focus_released_on_window_focus_released(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WindowFocusReleased:Connect(function() invokeFunction(callback_data, callback_vtable) end)); return createPointer(result_0); end +function abi.ffi.event_user_input_service_window_focused_on_window_focused_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WindowFocused:Connect(function() + invokeFunction(callback_data, callback_vtable) + end)); + return createPointer(result_0); +end function abi.ffi.event_user_input_service_window_focused_on_window_focused(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).WindowFocused:Connect(function() invokeFunction(callback_data, callback_vtable) @@ -13640,24 +15249,48 @@ end function abi.ffi.method_vr_service_set_touchpad_mode(self, pad, mode) getPointer(self):SetTouchpadMode(pad, mode) end +function abi.ffi.event_vr_service_navigation_requested_on_navigation_requested_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).NavigationRequested:Connect(function(cframe, input_user_c_frame) + invokeFunction(callback_data, callback_vtable, createPointer(cframe), input_user_c_frame) + end)); + return createPointer(result_0); +end function abi.ffi.event_vr_service_navigation_requested_on_navigation_requested(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).NavigationRequested:Connect(function(cframe, input_user_c_frame) invokeFunction(callback_data, callback_vtable, createPointer(cframe), input_user_c_frame) end)); return createPointer(result_0); end +function abi.ffi.event_vr_service_touchpad_mode_changed_on_touchpad_mode_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchpadModeChanged:Connect(function(pad, mode) + invokeFunction(callback_data, callback_vtable, pad, mode) + end)); + return createPointer(result_0); +end function abi.ffi.event_vr_service_touchpad_mode_changed_on_touchpad_mode_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).TouchpadModeChanged:Connect(function(pad, mode) invokeFunction(callback_data, callback_vtable, pad, mode) end)); return createPointer(result_0); end +function abi.ffi.event_vr_service_user_c_frame_changed_on_user_c_frame_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameChanged:Connect(function(type, value) + invokeFunction(callback_data, callback_vtable, type, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_vr_service_user_c_frame_changed_on_user_c_frame_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameChanged:Connect(function(type, value) invokeFunction(callback_data, callback_vtable, type, createPointer(value)) end)); return createPointer(result_0); end +function abi.ffi.event_vr_service_user_c_frame_enabled_on_user_c_frame_enabled_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameEnabled:Connect(function(type, enabled) + invokeFunction(callback_data, callback_vtable, type, enabled and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_vr_service_user_c_frame_enabled_on_user_c_frame_enabled(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).UserCFrameEnabled:Connect(function(type, enabled) invokeFunction(callback_data, callback_vtable, type, enabled and 1 or 0) @@ -13671,6 +15304,12 @@ end function abi.ffi.property_setter_bool_value_value_set_value(self, value) getPointer(self).Value = value == 1; end +function abi.ffi.event_bool_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, value and 1 or 0) + end)); + return createPointer(result_0); +end function abi.ffi.event_bool_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, value and 1 or 0) @@ -13684,6 +15323,12 @@ end function abi.ffi.property_setter_brick_color_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_brick_color_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_brick_color_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, createPointer(value)) @@ -13697,6 +15342,12 @@ end function abi.ffi.property_setter_c_frame_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_c_frame_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_c_frame_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, createPointer(value)) @@ -13710,6 +15361,12 @@ end function abi.ffi.property_setter_color_3_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_color_3_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_color_3_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, createPointer(value)) @@ -13723,6 +15380,12 @@ end function abi.ffi.property_setter_int_value_value_set_value(self, value) getPointer(self).Value = value; end +function abi.ffi.event_int_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, value) + end)); + return createPointer(result_0); +end function abi.ffi.event_int_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, value) @@ -13736,6 +15399,12 @@ end function abi.ffi.property_setter_number_value_value_set_value(self, value) getPointer(self).Value = value; end +function abi.ffi.event_number_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, value) + end)); + return createPointer(result_0); +end function abi.ffi.event_number_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, value) @@ -13753,6 +15422,16 @@ end function abi.ffi.property_setter_object_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_object_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + local value_optional, value_optional_0 = 0, 0; + if (value ~= nil) then + value_optional, value_optional_0 = 1, createPointer(value); + end + invokeFunction(callback_data, callback_vtable, value_optional, value_optional_0) + end)); + return createPointer(result_0); +end function abi.ffi.event_object_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) local value_optional, value_optional_0 = 0, 0; @@ -13770,6 +15449,12 @@ end function abi.ffi.property_setter_ray_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_ray_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_ray_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, createPointer(value)) @@ -13788,6 +15473,17 @@ end function abi.ffi.property_setter_string_value_value_set_value(self, value_addr, value_len) getPointer(self).Value = loadString(memory, value_addr, value_len); end +function abi.ffi.event_string_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + local value_len = #value; + local value_content = allocString(value_len); + for i = 1, value_len do + storeU8(memory, value_content + (i - 1), string.byte(value:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, value_content, value_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_string_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) local value_len = #value; @@ -13806,6 +15502,12 @@ end function abi.ffi.property_setter_vector_3_value_value_set_value(self, value) getPointer(self).Value = getPointer(value); end +function abi.ffi.event_vector_3_value_changed_on_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) + invokeFunction(callback_data, callback_vtable, createPointer(value)) + end)); + return createPointer(result_0); +end function abi.ffi.event_vector_3_value_changed_on_changed(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(value) invokeFunction(callback_data, callback_vtable, createPointer(value)) From c9c2596231a86e678e72dc8dd9525cc355cbe5ce Mon Sep 17 00:00:00 2001 From: fireboltofdeath <24422634+Fireboltofdeath@users.noreply.github.com> Date: Fri, 23 Jun 2023 14:31:18 -0400 Subject: [PATCH 4/5] WIP Refactor --- Cargo.toml | 33 +---- crates/codegen/Cargo.toml | 16 +++ {build => crates/codegen/src}/config.rs | 0 build/main.rs => crates/codegen/src/lib.rs | 38 ++---- .../codegen/src}/luau/constants.rs | 0 .../codegen/src}/luau/conversion.rs | 8 +- .../codegen/src}/luau/mod.rs | 16 +-- {build => crates/codegen/src}/overrides.rs | 40 +++++- .../codegen/src}/rust/constants.rs | 0 .../codegen/src}/rust/conversion.rs | 6 +- .../codegen/src}/rust/mod.rs | 19 +-- .../codegen/src}/rust/namespaces/datatypes.rs | 4 +- .../codegen/src}/rust/namespaces/functions.rs | 7 +- .../codegen/src}/rust/namespaces/instances.rs | 7 +- .../codegen/src}/rust/namespaces/mod.rs | 0 .../codegen/src}/structs/generation.rs | 3 +- .../codegen/src}/structs/implementations.rs | 2 +- .../codegen/src}/structs/layout.rs | 0 .../codegen/src}/structs/mod.rs | 0 .../codegen/src}/structs/types.rs | 0 .../codegen/src/transform_dump.rs | 16 +-- crates/roblox-dump/Cargo.toml | 11 ++ dump.json => crates/roblox-dump/dump.json | 0 crates/roblox-dump/src/lib.rs | 7 + .../dump => crates/roblox-dump/src}/types.rs | 8 -- crates/roblox-rs/Cargo.toml | 30 +++++ crates/roblox-rs/build.rs | 16 +++ .../roblox-rs/examples}/test.rs | 10 +- crates/roblox-rs/src/conversion/impls.rs | 77 +++++++++++ .../roblox-rs/src}/conversion/mod.rs | 2 +- .../roblox-rs/src}/conversion/structs.rs | 0 .../roblox-rs/src}/datatypes/lua_value.rs | 0 .../roblox-rs/src}/datatypes/mod.rs | 0 .../src}/datatypes/rbx_script_connection.rs | 1 + {src => crates/roblox-rs/src}/futures/ffi.rs | 0 {src => crates/roblox-rs/src}/futures/mod.rs | 0 {src => crates/roblox-rs/src}/futures/task.rs | 0 .../roblox-rs/src}/futures/waker.rs | 0 {src => crates/roblox-rs/src}/generated.rs | 0 {src => crates/roblox-rs/src}/lib.rs | 0 .../roblox-rs/src}/libraries/mod.rs | 0 .../roblox-rs/src}/libraries/standard.rs | 0 .../roblox-rs/src}/libraries/task.rs | 9 +- {src => crates/roblox-rs/src}/mem.rs | 0 crates/stream/Cargo.toml | 8 ++ crates/stream/src/lib.rs | 5 + .../codegen => crates/stream/src}/stream.rs | 15 ++- .../mod.rs => crates/stream/src/unique_ids.rs | 11 +- roblox/abi.luau | 121 +++++++++++++++++- src/conversion/impls.rs | 58 --------- 50 files changed, 409 insertions(+), 195 deletions(-) create mode 100644 crates/codegen/Cargo.toml rename {build => crates/codegen/src}/config.rs (100%) rename build/main.rs => crates/codegen/src/lib.rs (70%) rename {build/codegen => crates/codegen/src}/luau/constants.rs (100%) rename {build/codegen => crates/codegen/src}/luau/conversion.rs (98%) rename {build/codegen => crates/codegen/src}/luau/mod.rs (96%) rename {build => crates/codegen/src}/overrides.rs (91%) rename {build/codegen => crates/codegen/src}/rust/constants.rs (100%) rename {build/codegen => crates/codegen/src}/rust/conversion.rs (99%) rename {build/codegen => crates/codegen/src}/rust/mod.rs (96%) rename {build/codegen => crates/codegen/src}/rust/namespaces/datatypes.rs (97%) rename {build/codegen => crates/codegen/src}/rust/namespaces/functions.rs (92%) rename {build/codegen => crates/codegen/src}/rust/namespaces/instances.rs (98%) rename {build/codegen => crates/codegen/src}/rust/namespaces/mod.rs (100%) rename {build/codegen => crates/codegen/src}/structs/generation.rs (99%) rename {build/codegen => crates/codegen/src}/structs/implementations.rs (98%) rename {build/codegen => crates/codegen/src}/structs/layout.rs (100%) rename {build/codegen => crates/codegen/src}/structs/mod.rs (100%) rename {build/codegen => crates/codegen/src}/structs/types.rs (100%) rename build/dump/mod.rs => crates/codegen/src/transform_dump.rs (98%) create mode 100644 crates/roblox-dump/Cargo.toml rename dump.json => crates/roblox-dump/dump.json (100%) create mode 100644 crates/roblox-dump/src/lib.rs rename {build/dump => crates/roblox-dump/src}/types.rs (95%) create mode 100644 crates/roblox-rs/Cargo.toml create mode 100644 crates/roblox-rs/build.rs rename {examples => crates/roblox-rs/examples}/test.rs (93%) create mode 100644 crates/roblox-rs/src/conversion/impls.rs rename {src => crates/roblox-rs/src}/conversion/mod.rs (93%) rename {src => crates/roblox-rs/src}/conversion/structs.rs (100%) rename {src => crates/roblox-rs/src}/datatypes/lua_value.rs (100%) rename {src => crates/roblox-rs/src}/datatypes/mod.rs (100%) rename {src => crates/roblox-rs/src}/datatypes/rbx_script_connection.rs (90%) rename {src => crates/roblox-rs/src}/futures/ffi.rs (100%) rename {src => crates/roblox-rs/src}/futures/mod.rs (100%) rename {src => crates/roblox-rs/src}/futures/task.rs (100%) rename {src => crates/roblox-rs/src}/futures/waker.rs (100%) rename {src => crates/roblox-rs/src}/generated.rs (100%) rename {src => crates/roblox-rs/src}/lib.rs (100%) rename {src => crates/roblox-rs/src}/libraries/mod.rs (100%) rename {src => crates/roblox-rs/src}/libraries/standard.rs (100%) rename {src => crates/roblox-rs/src}/libraries/task.rs (71%) rename {src => crates/roblox-rs/src}/mem.rs (100%) create mode 100644 crates/stream/Cargo.toml create mode 100644 crates/stream/src/lib.rs rename {build/codegen => crates/stream/src}/stream.rs (93%) rename build/codegen/mod.rs => crates/stream/src/unique_ids.rs (88%) delete mode 100644 src/conversion/impls.rs diff --git a/Cargo.toml b/Cargo.toml index 4696ca8..bb48a90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,29 +1,10 @@ -[package] -name = "roblox_rs" -version = "0.1.0" -authors = ["Firebolt <24422634+Fireboltofdeath@users.noreply.github.com>"] -edition = "2018" -build = "./build/main.rs" - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -# Smaller allocator -wee_alloc = { version = "0.4.5" } - -[build_dependencies] -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -serde_with = "1.14.0" -convert_case = "0.5" -lazy_static = "1.4" -chrono = "0.4" - -[features] -default = ["multivalue"] -multivalue = [] -deprecated_apis = [] +[workspace] +members = [ + "crates/roblox-rs", + "crates/roblox-dump", + "crates/codegen", + "crates/stream" +] [profile.dev] # optimize for size even on dev to prevent excessive locals diff --git a/crates/codegen/Cargo.toml b/crates/codegen/Cargo.toml new file mode 100644 index 0000000..9f28637 --- /dev/null +++ b/crates/codegen/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "codegen" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +stream = { path = "../stream" } +roblox-dump = { path = "../roblox-dump" } +lazy_static = "1.4" +convert_case = "0.5" + +[features] +multivalue = [] +deprecated_apis = [] diff --git a/build/config.rs b/crates/codegen/src/config.rs similarity index 100% rename from build/config.rs rename to crates/codegen/src/config.rs diff --git a/build/main.rs b/crates/codegen/src/lib.rs similarity index 70% rename from build/main.rs rename to crates/codegen/src/lib.rs index 1564584..f23f129 100644 --- a/build/main.rs +++ b/crates/codegen/src/lib.rs @@ -1,34 +1,27 @@ -mod codegen; mod config; -mod dump; +pub mod luau; mod overrides; -// mod macros; +pub mod rust; +mod structs; +mod transform_dump; -use codegen::{ - luau, rust, - structs::{Namespace, NamespaceKind}, -}; use config::DATATYPES; -use dump::{transform_dump, types::Dump}; use overrides::{get_datatypes, get_instances, internal_namespace}; -use std::{env, fs, path::Path}; - -fn main() { - let output = env::var("OUT_DIR").unwrap(); - let dump = &serde_json::from_slice::( - fs::read("./dump.json") - .expect("Dump could not be read.") - .as_slice(), - ) - .expect("could not deserialize dump"); +use roblox_dump::Dump; +use structs::{Namespace, NamespaceKind}; +use transform_dump::transform_dump; +pub fn get_namespaces(dump: &Dump) -> Vec { let mut namespaces = transform_dump(dump); let instance_overrides = get_instances(); for partial in instance_overrides.into_iter() { if let Some(namespace) = namespaces.iter_mut().find(|v| v.name == partial.name) { - for member in partial.members.into_iter() { + for member in partial.members.iter() { namespace.members.retain(|v| v.api_name != member.api_name); + } + + for member in partial.members.into_iter() { namespace.members.push(member); } } @@ -68,10 +61,5 @@ fn main() { } } - fs::write("./roblox/abi.luau", luau::generate(&namespaces)).unwrap(); - fs::write( - Path::new(&output).join("generated.rs"), - rust::generate(&namespaces, &dump.enums), - ) - .unwrap(); + namespaces } diff --git a/build/codegen/luau/constants.rs b/crates/codegen/src/luau/constants.rs similarity index 100% rename from build/codegen/luau/constants.rs rename to crates/codegen/src/luau/constants.rs diff --git a/build/codegen/luau/conversion.rs b/crates/codegen/src/luau/conversion.rs similarity index 98% rename from build/codegen/luau/conversion.rs rename to crates/codegen/src/luau/conversion.rs index 544813e..5da2437 100644 --- a/build/codegen/luau/conversion.rs +++ b/crates/codegen/src/luau/conversion.rs @@ -1,10 +1,6 @@ -use crate::codegen::{ - stream::{note, pull, push, Stream}, - structs::{CodegenKind, Parameter}, - UniqueIds, -}; - use super::{load_memory, store_memory}; +use crate::structs::{CodegenKind, Parameter}; +use stream::{note, pull, push, Stream, UniqueIds}; fn convert_vec( identifier: &str, diff --git a/build/codegen/luau/mod.rs b/crates/codegen/src/luau/mod.rs similarity index 96% rename from build/codegen/luau/mod.rs rename to crates/codegen/src/luau/mod.rs index f55f56d..c5665e4 100644 --- a/build/codegen/luau/mod.rs +++ b/crates/codegen/src/luau/mod.rs @@ -1,18 +1,12 @@ -pub mod constants; +mod constants; mod conversion; -use crate::codegen::{ - luau::constants::{LUAU_CREATE_CONNECTION, LUAU_DISCONNECT_CONNECTION, LUA_VALUE_NUMBER_TYPES}, - stream::{note, pull, push}, - UniqueIds, -}; - use self::conversion::{convert_luau_to_rust, convert_rust_to_luau}; - -use super::{ - stream::Stream, - structs::{CodegenKind, Member, Namespace, RenderData, Representation, TypeLayout}, +use crate::luau::constants::{ + LUAU_CREATE_CONNECTION, LUAU_DISCONNECT_CONNECTION, LUA_VALUE_NUMBER_TYPES, }; +use crate::structs::{CodegenKind, Member, Namespace, RenderData, Representation, TypeLayout}; +use stream::{note, pull, push, Stream, UniqueIds}; fn store_memory(layout: TypeLayout, address: &str, inputs: &[String]) -> String { Stream::expression(|stream| { diff --git a/build/overrides.rs b/crates/codegen/src/overrides.rs similarity index 91% rename from build/overrides.rs rename to crates/codegen/src/overrides.rs index 60cd080..8d41341 100644 --- a/build/overrides.rs +++ b/crates/codegen/src/overrides.rs @@ -1,8 +1,6 @@ use convert_case::{Case, Casing}; -use crate::codegen::structs::{ - implementations::*, Async, CodegenKind, Member, MemberFlags, Parameter, -}; +use crate::structs::{implementations::*, Async, CodegenKind, Member, MemberFlags, Parameter}; pub struct PartialNamespace { /// Name of this namespace @@ -191,6 +189,14 @@ pub fn internal_namespace() -> PartialNamespace { new::instance_new(StaticFunction(Some("Instance"), None)); signature = (class_name: string) -> instance!(Instance); }, + member! { + task_wait(StaticFunction(Some("task"), Some("wait"))); + signature = (time: number) -> number; + flags = MemberFlags { + yielding: true, + ..MemberFlags::default() + }; + }, ], } } @@ -284,6 +290,20 @@ macro_rules! parse_namespace_fields { ) -> (datatype!(RbxScriptConnection)); }); + $namespace.members.push(member! { + $api_name(Event); + + name = format!("{}_async", stringify!($name).to_case(Case::Snake)); + signature = ( + self: $kind, + callback: CodegenKind::Function( + vec![$(Parameter::new(stringify!($parameter), $type.clone())),*], + Box::new(CodegenKind::Void), + Async::Yes + ) + ) -> (datatype!(RbxScriptConnection)); + }); + parse_namespace_fields!(($namespace;$kind) $($tt)*); }; (($namespace:expr;$kind:expr) event $name:ident($($parameter:ident : $type:expr),*); $($tt:tt)*) => { @@ -295,6 +315,20 @@ macro_rules! parse_namespace_fields { $namespace.members.push(member! { $api_name::$name(Callback); + signature = ( + self: $kind, + callback: CodegenKind::Function( + vec![$(Parameter::new(stringify!($parameter), $type.clone())),*], + Box::new($result.clone()), + Async::No + ) + ) -> (); + }); + + $namespace.members.push(member! { + $api_name(Callback); + + name = format!("{}_async", stringify!($name).to_case(Case::Snake)); signature = ( self: $kind, callback: CodegenKind::Function( diff --git a/build/codegen/rust/constants.rs b/crates/codegen/src/rust/constants.rs similarity index 100% rename from build/codegen/rust/constants.rs rename to crates/codegen/src/rust/constants.rs diff --git a/build/codegen/rust/conversion.rs b/crates/codegen/src/rust/conversion.rs similarity index 99% rename from build/codegen/rust/conversion.rs rename to crates/codegen/src/rust/conversion.rs index f65b964..7990f07 100644 --- a/build/codegen/rust/conversion.rs +++ b/crates/codegen/src/rust/conversion.rs @@ -1,7 +1,5 @@ -use crate::codegen::{ - stream::{note, pull, push, Stream}, - structs::{Async, CodegenKind}, -}; +use crate::structs::{Async, CodegenKind}; +use stream::{note, pull, push, Stream}; use super::raw_name; diff --git a/build/codegen/rust/mod.rs b/crates/codegen/src/rust/mod.rs similarity index 96% rename from build/codegen/rust/mod.rs rename to crates/codegen/src/rust/mod.rs index e9471fe..620a6ba 100644 --- a/build/codegen/rust/mod.rs +++ b/crates/codegen/src/rust/mod.rs @@ -1,11 +1,4 @@ -use crate::{ - codegen::{ - rust::conversion::owned_ffi_to_rust, - stream::{note, pull, write_to}, - structs::Async, - }, - dump::types::Enum, -}; +use roblox_dump::Enum; use self::{ constants::{ @@ -20,11 +13,13 @@ use self::{ datatypes::generate_datatypes, functions::generate_functions, instances::generate_instances, }, }; - -use super::{ - stream::{push, Stream}, - structs::{CodegenKind, DeclarationContext, Member, Namespace, NamespaceKind, Parameter}, +use crate::{ + rust::conversion::owned_ffi_to_rust, + structs::{ + Async, CodegenKind, DeclarationContext, Member, Namespace, NamespaceKind, Parameter, + }, }; +use stream::{note, pull, push, write_to, Stream}; mod constants; mod conversion; diff --git a/build/codegen/rust/namespaces/datatypes.rs b/crates/codegen/src/rust/namespaces/datatypes.rs similarity index 97% rename from build/codegen/rust/namespaces/datatypes.rs rename to crates/codegen/src/rust/namespaces/datatypes.rs index 4c03cf7..a85b1df 100644 --- a/build/codegen/rust/namespaces/datatypes.rs +++ b/crates/codegen/src/rust/namespaces/datatypes.rs @@ -1,11 +1,11 @@ -use crate::codegen::{ +use crate::{ rust::{ constants::DATATYPE_IMPL_MACRO, conversion::get_owned_rust_type, generate_body, generate_member, }, - stream::{note, pull, push, Stream}, structs::{DeclarationContext, Member, Namespace}, }; +use stream::{note, pull, push, Stream}; fn generate_operator(output: &mut Vec, namespace: &Namespace, member: &Member, op: &str) { let class = &namespace.name; diff --git a/build/codegen/rust/namespaces/functions.rs b/crates/codegen/src/rust/namespaces/functions.rs similarity index 92% rename from build/codegen/rust/namespaces/functions.rs rename to crates/codegen/src/rust/namespaces/functions.rs index 2283c83..47d4c88 100644 --- a/build/codegen/rust/namespaces/functions.rs +++ b/crates/codegen/src/rust/namespaces/functions.rs @@ -1,10 +1,9 @@ -use convert_case::{Case, Casing}; - -use crate::codegen::{ +use crate::{ rust::generate_member, - stream::{note, pull, push, Stream}, structs::{DeclarationContext, Namespace}, }; +use convert_case::{Case, Casing}; +use stream::{note, pull, push, Stream}; pub fn generate_functions(output: &mut Vec, namespaces: &[&Namespace]) { for namespace in namespaces { diff --git a/build/codegen/rust/namespaces/instances.rs b/crates/codegen/src/rust/namespaces/instances.rs similarity index 98% rename from build/codegen/rust/namespaces/instances.rs rename to crates/codegen/src/rust/namespaces/instances.rs index d53dc62..e4f3ddb 100644 --- a/build/codegen/rust/namespaces/instances.rs +++ b/crates/codegen/src/rust/namespaces/instances.rs @@ -1,6 +1,4 @@ -use convert_case::{Case, Casing}; - -use crate::codegen::{ +use crate::{ rust::{ constants::{ CUSTOM_IMPL_DATA_MODEL, CUSTOM_IMPL_INSTANCE, CUSTOM_IMPL_SERVICE, @@ -8,9 +6,10 @@ use crate::codegen::{ }, generate_member, generate_member_declaration, }, - stream::{note, pull, push, Stream}, structs::{DeclarationContext, Namespace, NamespaceKind}, }; +use convert_case::{Case, Casing}; +use stream::{note, pull, push, Stream}; fn generate_custom_impl(output: &mut Vec, namespace: &Namespace) { let NamespaceKind::Instance(metadata) = &namespace.kind else { unreachable!() }; diff --git a/build/codegen/rust/namespaces/mod.rs b/crates/codegen/src/rust/namespaces/mod.rs similarity index 100% rename from build/codegen/rust/namespaces/mod.rs rename to crates/codegen/src/rust/namespaces/mod.rs diff --git a/build/codegen/structs/generation.rs b/crates/codegen/src/structs/generation.rs similarity index 99% rename from build/codegen/structs/generation.rs rename to crates/codegen/src/structs/generation.rs index fde85d4..6a231ac 100644 --- a/build/codegen/structs/generation.rs +++ b/crates/codegen/src/structs/generation.rs @@ -1,6 +1,5 @@ use convert_case::{Case, Casing}; - -use crate::codegen::UniqueIds; +use stream::UniqueIds; use super::{implementations::Implementation, CodegenKind}; diff --git a/build/codegen/structs/implementations.rs b/crates/codegen/src/structs/implementations.rs similarity index 98% rename from build/codegen/structs/implementations.rs rename to crates/codegen/src/structs/implementations.rs index f20afa7..15c38ba 100644 --- a/build/codegen/structs/implementations.rs +++ b/crates/codegen/src/structs/implementations.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use crate::codegen::stream::{note, Stream}; +use stream::{note, Stream}; use super::{MemberImplementation, RenderData}; diff --git a/build/codegen/structs/layout.rs b/crates/codegen/src/structs/layout.rs similarity index 100% rename from build/codegen/structs/layout.rs rename to crates/codegen/src/structs/layout.rs diff --git a/build/codegen/structs/mod.rs b/crates/codegen/src/structs/mod.rs similarity index 100% rename from build/codegen/structs/mod.rs rename to crates/codegen/src/structs/mod.rs diff --git a/build/codegen/structs/types.rs b/crates/codegen/src/structs/types.rs similarity index 100% rename from build/codegen/structs/types.rs rename to crates/codegen/src/structs/types.rs diff --git a/build/dump/mod.rs b/crates/codegen/src/transform_dump.rs similarity index 98% rename from build/dump/mod.rs rename to crates/codegen/src/transform_dump.rs index 3f1f5d5..f62a0cb 100644 --- a/build/dump/mod.rs +++ b/crates/codegen/src/transform_dump.rs @@ -1,21 +1,17 @@ -pub mod types; - use convert_case::{Case, Casing}; -use types::{ - Class, ClassEventMember, ClassFunctionMember, ClassMember, ClassPropertyMember, DataTypeKind, - Dump, PrimitiveKind, Security, ValueType, +use roblox_dump::{ + Class, ClassCallbackMember, ClassEventMember, ClassFunctionMember, ClassMember, + ClassPropertyMember, DataTypeKind, Dump, PrimitiveKind, Security, ValueType, }; use crate::{ - codegen::structs::{ + config::{CLASS_BLACKLIST, DEPRECATED_APIS}, + structs::{ implementations, Async, CodegenKind, InstanceMetadata, Member, MemberFlags, Namespace, NamespaceKind, Parameter, }, - config::{CLASS_BLACKLIST, DEPRECATED_APIS}, }; -use self::types::ClassCallbackMember; - enum SecurityKind { Read, Write, @@ -374,7 +370,7 @@ fn transform_class_member(dump: &Dump, class: &Class, member: &ClassMember) -> V } match member { - ClassMember::Event(event) => transform_class_event(dump, event).into_iter().collect(), + ClassMember::Event(event) => transform_class_event(dump, event), ClassMember::Property(property) => transform_class_property(dump, property), ClassMember::Function(function) => transform_class_function(dump, class, function) .into_iter() diff --git a/crates/roblox-dump/Cargo.toml b/crates/roblox-dump/Cargo.toml new file mode 100644 index 0000000..8c9b064 --- /dev/null +++ b/crates/roblox-dump/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "roblox-dump" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +serde_with = "1.14.0" diff --git a/dump.json b/crates/roblox-dump/dump.json similarity index 100% rename from dump.json rename to crates/roblox-dump/dump.json diff --git a/crates/roblox-dump/src/lib.rs b/crates/roblox-dump/src/lib.rs new file mode 100644 index 0000000..caea3bf --- /dev/null +++ b/crates/roblox-dump/src/lib.rs @@ -0,0 +1,7 @@ +mod types; + +pub use types::*; + +pub fn get_dump() -> Dump { + serde_json::from_str::(include_str!("../dump.json")).expect("could not deserialize dump") +} diff --git a/build/dump/types.rs b/crates/roblox-dump/src/types.rs similarity index 95% rename from build/dump/types.rs rename to crates/roblox-dump/src/types.rs index 0297481..9eb7932 100644 --- a/build/dump/types.rs +++ b/crates/roblox-dump/src/types.rs @@ -61,10 +61,6 @@ pub struct ClassEventMember { pub tags: HashSet, pub security: Security, pub parameters: Vec, - - /// The real Roblox event name. - /// This differs from name in cases like `Instance.Changed` - pub event_name: Option, } #[derive(Clone, Deserialize, PartialEq, Eq)] @@ -89,10 +85,6 @@ pub struct ClassFunctionMember { pub tags: HashSet, pub security: Security, pub parameters: Vec, - - /// The real Roblox function name. - /// This differs from name in case of collisions like SetAxis() and .Axis = - pub func_name: Option, } #[derive(Clone, Deserialize, PartialEq, Eq)] diff --git a/crates/roblox-rs/Cargo.toml b/crates/roblox-rs/Cargo.toml new file mode 100644 index 0000000..9893c82 --- /dev/null +++ b/crates/roblox-rs/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "roblox-rs" +version = "0.1.0" +authors = ["Firebolt <24422634+Fireboltofdeath@users.noreply.github.com>"] +edition = "2018" +build = "./build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +# Smaller allocator +wee_alloc = { version = "0.4.5" } + +[build_dependencies] +serde = { version = "1.0", features = ["derive"] } +roblox-dump = { path = "../roblox-dump" } +codegen = { path = "../codegen" } +serde_json = "1.0" +serde_with = "1.14.0" +convert_case = "0.5" +lazy_static = "1.4" +chrono = "0.4" + +[features] +default = ["multivalue"] +multivalue = ["codegen/multivalue"] +deprecated_apis = ["codegen/deprecated_apis"] diff --git a/crates/roblox-rs/build.rs b/crates/roblox-rs/build.rs new file mode 100644 index 0000000..e189fb4 --- /dev/null +++ b/crates/roblox-rs/build.rs @@ -0,0 +1,16 @@ +use codegen::{get_namespaces, luau, rust}; +use roblox_dump::get_dump; +use std::{env, fs, path::Path}; + +fn main() { + let output = env::var("OUT_DIR").unwrap(); + let dump = get_dump(); + let namespaces = get_namespaces(&dump); + + fs::write("../../roblox/abi.luau", luau::generate(&namespaces)).unwrap(); + fs::write( + Path::new(&output).join("generated.rs"), + rust::generate(&namespaces, &dump.enums), + ) + .unwrap(); +} diff --git a/examples/test.rs b/crates/roblox-rs/examples/test.rs similarity index 93% rename from examples/test.rs rename to crates/roblox-rs/examples/test.rs index de2cc87..c62cec8 100644 --- a/examples/test.rs +++ b/crates/roblox-rs/examples/test.rs @@ -36,6 +36,11 @@ pub fn main() { CollectionService::instance().add_tag(&Workspace::instance(), "god1"); CollectionService::instance().add_tag(&Workspace::instance(), "god2"); CollectionService::instance().add_tag(&Workspace::instance(), "god3"); + Workspace::instance() + .on_instance_changed_async(|v| async move { + println!("connected async! {v}, {}", task::wait(1.0).await); + }) + .leak(); for tag in CollectionService::instance().get_tags(&Workspace::instance()) { println!("workspace has tag: {tag}"); @@ -43,7 +48,7 @@ pub fn main() { let value = "Workspace".to_string(); - let connection = Workspace::instance().on_instance_changed(|name| { + let connection = Workspace::instance().on_instance_changed(|_name| { // println!("On instance changed!!!, {}", name); }); @@ -82,12 +87,13 @@ pub fn main() { my_func.set_name("GOD FUNC"); my_func.set_parent(&Some(&Workspace::instance())); - my_func.on_server_invoke(move |player, values| async move { + my_func.on_server_invoke_async(move |player, values| async move { println!( "Wow, {} sent me messages that I will respond to:", player.name() ); for (i, message) in values.into_iter().enumerate() { + task::wait(1.0).await; if let Ok(str) = String::try_from(message) { println!("got string: {str}"); } else { diff --git a/crates/roblox-rs/src/conversion/impls.rs b/crates/roblox-rs/src/conversion/impls.rs new file mode 100644 index 0000000..7a6356b --- /dev/null +++ b/crates/roblox-rs/src/conversion/impls.rs @@ -0,0 +1,77 @@ +use std::slice; + +use super::{ + foreign, + structs::{RustOption, RustSlice, RustString}, + FromForeign, IntoForeign, +}; + +impl IntoForeign for Option { + type Output = RustOption; + + fn into_foreign(self) -> Self::Output { + match self { + Some(value) => RustOption::Some(value.into_foreign()), + None => RustOption::None, + } + } +} + +impl FromForeign for Option { + type Input = RustOption; + + fn from_foreign(value: &Self::Input) -> Self { + match value { + RustOption::Some(value) => Some(T::from_foreign(value)), + RustOption::None => None, + } + } +} + +impl FromForeign for String { + type Input = RustString; + + fn from_foreign(input: &Self::Input) -> Self { + unsafe { String::from_raw_parts(input.content, input.length, input.length) } + } +} + +// We cannot IntoForeign for slices (currently) as we must map the entirety of the slice +// using T::into_foreign, however that would involve creating a new slice which must be kept alive past the scope of the function. +// Not clear yet how to implement this. +// impl IntoForeign for &[T] { +// type Output = RustSlice; + +// fn into_foreign(self) -> Self::Output { +// RustSlice { +// content: self.as_ptr(), +// length: self.len(), +// } +// } +// } + +// IntoForeign for Vec is also problematic (currently) as we don't have a Foreign owned array (there is RustSlice, but it is a reference) +// impl IntoForeign for Vec { +// type Output = Vec; + +// fn into_foreign(self) -> Self::Output { +// self.into_iter().map(|v| v.into_foreign()).collect() +// } +// } + +impl FromForeign for Vec { + type Input = RustSlice; + + fn from_foreign(input: &Self::Input) -> Self { + unsafe { slice::from_raw_parts(input.content, input.length) } + .iter() + .map(|v| T::from_foreign(v)) + .collect() + } +} + +// impl IntoForeign for &[T] { +// type Output = RustSlice; +// } + +foreign!(i8 u8 i16 u16 i32 u32 f32 i64 u64 f64 RustString RustSlice RustOption); diff --git a/src/conversion/mod.rs b/crates/roblox-rs/src/conversion/mod.rs similarity index 93% rename from src/conversion/mod.rs rename to crates/roblox-rs/src/conversion/mod.rs index 8a1202c..efb8334 100644 --- a/src/conversion/mod.rs +++ b/crates/roblox-rs/src/conversion/mod.rs @@ -15,7 +15,7 @@ pub trait IntoForeign { pub trait FromForeign { type Input: Foreign; - fn from_foreign(input: Self::Input) -> Self; + fn from_foreign(input: &Self::Input) -> Self; } macro_rules! foreign { diff --git a/src/conversion/structs.rs b/crates/roblox-rs/src/conversion/structs.rs similarity index 100% rename from src/conversion/structs.rs rename to crates/roblox-rs/src/conversion/structs.rs diff --git a/src/datatypes/lua_value.rs b/crates/roblox-rs/src/datatypes/lua_value.rs similarity index 100% rename from src/datatypes/lua_value.rs rename to crates/roblox-rs/src/datatypes/lua_value.rs diff --git a/src/datatypes/mod.rs b/crates/roblox-rs/src/datatypes/mod.rs similarity index 100% rename from src/datatypes/mod.rs rename to crates/roblox-rs/src/datatypes/mod.rs diff --git a/src/datatypes/rbx_script_connection.rs b/crates/roblox-rs/src/datatypes/rbx_script_connection.rs similarity index 90% rename from src/datatypes/rbx_script_connection.rs rename to crates/roblox-rs/src/datatypes/rbx_script_connection.rs index 7eeef60..261867d 100644 --- a/src/datatypes/rbx_script_connection.rs +++ b/crates/roblox-rs/src/datatypes/rbx_script_connection.rs @@ -5,6 +5,7 @@ extern "C" { fn is_connected(connection: u32) -> bool; } +#[must_use = "connections are disconnected when dropped"] #[repr(transparent)] pub struct RbxScriptConnection(pub(crate) u32); diff --git a/src/futures/ffi.rs b/crates/roblox-rs/src/futures/ffi.rs similarity index 100% rename from src/futures/ffi.rs rename to crates/roblox-rs/src/futures/ffi.rs diff --git a/src/futures/mod.rs b/crates/roblox-rs/src/futures/mod.rs similarity index 100% rename from src/futures/mod.rs rename to crates/roblox-rs/src/futures/mod.rs diff --git a/src/futures/task.rs b/crates/roblox-rs/src/futures/task.rs similarity index 100% rename from src/futures/task.rs rename to crates/roblox-rs/src/futures/task.rs diff --git a/src/futures/waker.rs b/crates/roblox-rs/src/futures/waker.rs similarity index 100% rename from src/futures/waker.rs rename to crates/roblox-rs/src/futures/waker.rs diff --git a/src/generated.rs b/crates/roblox-rs/src/generated.rs similarity index 100% rename from src/generated.rs rename to crates/roblox-rs/src/generated.rs diff --git a/src/lib.rs b/crates/roblox-rs/src/lib.rs similarity index 100% rename from src/lib.rs rename to crates/roblox-rs/src/lib.rs diff --git a/src/libraries/mod.rs b/crates/roblox-rs/src/libraries/mod.rs similarity index 100% rename from src/libraries/mod.rs rename to crates/roblox-rs/src/libraries/mod.rs diff --git a/src/libraries/standard.rs b/crates/roblox-rs/src/libraries/standard.rs similarity index 100% rename from src/libraries/standard.rs rename to crates/roblox-rs/src/libraries/standard.rs diff --git a/src/libraries/task.rs b/crates/roblox-rs/src/libraries/task.rs similarity index 71% rename from src/libraries/task.rs rename to crates/roblox-rs/src/libraries/task.rs index a1ce0bb..d1e37dd 100644 --- a/src/libraries/task.rs +++ b/crates/roblox-rs/src/libraries/task.rs @@ -1,11 +1,11 @@ -use crate::futures::ffi::LuaFuture; +use crate::internal; #[allow(improper_ctypes)] extern "C" { fn lib_task_delay(amount: f64, task: Box); fn lib_task_defer(task: Box); fn lib_task_spawn(task: Box); - fn lib_task_wait(amount: f64) -> LuaFuture; + // fn lib_task_wait(amount: f64) -> LuaFuture; } pub fn delay(amount: f64, value: F) { @@ -20,6 +20,7 @@ pub fn spawn(value: F) { unsafe { lib_task_spawn(Box::new(value)) } } -pub fn wait(amount: f64) -> LuaFuture { - unsafe { lib_task_wait(amount) } +pub async fn wait(amount: f64) -> f64 { + // unsafe { lib_task_wait(amount) } + internal::task_wait(amount).await } diff --git a/src/mem.rs b/crates/roblox-rs/src/mem.rs similarity index 100% rename from src/mem.rs rename to crates/roblox-rs/src/mem.rs diff --git a/crates/stream/Cargo.toml b/crates/stream/Cargo.toml new file mode 100644 index 0000000..90bf796 --- /dev/null +++ b/crates/stream/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "stream" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/stream/src/lib.rs b/crates/stream/src/lib.rs new file mode 100644 index 0000000..90af63d --- /dev/null +++ b/crates/stream/src/lib.rs @@ -0,0 +1,5 @@ +mod stream; +mod unique_ids; + +pub use stream::*; +pub use unique_ids::*; diff --git a/build/codegen/stream.rs b/crates/stream/src/stream.rs similarity index 93% rename from build/codegen/stream.rs rename to crates/stream/src/stream.rs index 4e3b2b5..3fe7033 100644 --- a/build/codegen/stream.rs +++ b/crates/stream/src/stream.rs @@ -59,6 +59,13 @@ impl Stream { } } +impl Default for Stream { + fn default() -> Self { + Self::new() + } +} + +#[macro_export] macro_rules! note { ($name:ident in $list:ident) => { if !$list.is_empty() { @@ -73,25 +80,23 @@ macro_rules! note { } } +#[macro_export] macro_rules! push { ($name:ident, $($tts:tt)*) => { $name.push(&format!($($tts)*)) } } +#[macro_export] macro_rules! pull { ($name:ident, $($tts:tt)*) => { $name.pop(&format!($($tts)*)) } } +#[macro_export] macro_rules! write_to { ($name:ident, $($tts:tt)*) => { $name.write(&format!($($tts)*)) } } - -pub(crate) use note; -pub(crate) use pull; -pub(crate) use push; -pub(crate) use write_to; diff --git a/build/codegen/mod.rs b/crates/stream/src/unique_ids.rs similarity index 88% rename from build/codegen/mod.rs rename to crates/stream/src/unique_ids.rs index 3d065e3..fbbfaeb 100644 --- a/build/codegen/mod.rs +++ b/crates/stream/src/unique_ids.rs @@ -3,11 +3,6 @@ use std::{ collections::HashMap, }; -pub mod luau; -pub mod rust; -pub mod stream; -pub mod structs; - #[derive(Clone)] pub struct UniqueIds(Cell, RefCell>); @@ -29,3 +24,9 @@ impl UniqueIds { } } } + +impl Default for UniqueIds { + fn default() -> Self { + Self::new() + } +} diff --git a/roblox/abi.luau b/roblox/abi.luau index 8fcc9e6..1b53e2f 100644 --- a/roblox/abi.luau +++ b/roblox/abi.luau @@ -302,6 +302,14 @@ function abi.ffi.event_instance_destroying_on_destroying(self, callback_data, ca end)); return createPointer(result_0); end +function abi.ffi.property_getter_instance_parent(self) + local result_0 = getPointer(self).Parent; + local result_0_optional, result_0_optional_0 = 0, 0; + if (result_0 ~= nil) then + result_0_optional, result_0_optional_0 = 1, createPointer(result_0); + end + return result_0_optional, result_0_optional_0; +end function abi.ffi.property_setter_instance_parent_set_parent(self, value_kind, value) local value_optional; if (value_kind == 1) then @@ -320,6 +328,17 @@ function abi.ffi.event_instance_changed_on_instance_changed(self, callback_data, end)); return createPointer(result_0); end +function abi.ffi.event_instance_changed_on_instance_changed_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Changed:Connect(function(property) + local property_len = #property; + local property_content = allocString(property_len); + for i = 1, property_len do + storeU8(memory, property_content + (i - 1), string.byte(property:sub(i, i))); + end + invokeFunction(callback_data, callback_vtable, property_content, property_len) + end)); + return createPointer(result_0); +end function abi.ffi.property_getter_accoutrement_attachment_forward(self) local result_0 = getPointer(self).AttachmentForward; return createPointer(result_0); @@ -1470,6 +1489,19 @@ function abi.ffi.event_bindable_event_event(self, callback_data, callback_vtable end)); return createPointer(result_0); end +function abi.ffi.event_bindable_event_event_event_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Event:Connect(function(...) + local values_tuple = { ... }; + local values_len = select("#", ...); + local values_tuple_vec = allocVec(values_len * 4) + for i = 1, values_len do + local values_tuple_vec_value = values_tuple[i]; + storeU32(memory, values_tuple_vec + (i - 1) * 4 + 0, createPointer(values_tuple_vec_value)); + end + invokeFunction(callback_data, callback_vtable, values_tuple_vec, values_len) + end)); + return createPointer(result_0); +end function abi.ffi.method_bindable_event_fire(self, values_addr, values_len) local values_vec = table.create(values_len); for i = 1, values_len do @@ -7473,6 +7505,12 @@ function abi.ffi.event_humanoid_touched_on_humanoid_touched(self, callback_data, end)); return createPointer(result_0); end +function abi.ffi.event_humanoid_touched_on_humanoid_touched_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Touched:Connect(function(part, limb) + invokeFunction(callback_data, callback_vtable, createPointer(part), createPointer(limb)) + end)); + return createPointer(result_0); +end function abi.ffi.property_getter_humanoid_description_back_accessory(self) local result_0 = getPointer(self).BackAccessory; local result_0_len = #result_0; @@ -9657,6 +9695,12 @@ function abi.ffi.event_base_part_touched_on_touched(self, callback_data, callbac end)); return createPointer(result_0); end +function abi.ffi.event_base_part_touched_on_touched_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).Touched:Connect(function(part) + invokeFunction(callback_data, callback_vtable, createPointer(part)) + end)); + return createPointer(result_0); +end function abi.ffi.property_getter_part_shape(self) local result_0 = getPointer(self).Shape; return result_0; @@ -11807,6 +11851,19 @@ function abi.ffi.event_remote_event_on_server_event(self, callback_data, callbac end)); return createPointer(result_0); end +function abi.ffi.event_remote_event_on_server_event_on_server_event_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).OnServerEvent:Connect(function(player, ...) + local values_tuple = { ... }; + local values_len = select("#", ...); + local values_tuple_vec = allocVec(values_len * 4) + for i = 1, values_len do + local values_tuple_vec_value = values_tuple[i]; + storeU32(memory, values_tuple_vec + (i - 1) * 4 + 0, createPointer(values_tuple_vec_value)); + end + invokeFunction(callback_data, callback_vtable, createPointer(player), values_tuple_vec, values_len) + end)); + return createPointer(result_0); +end function abi.ffi.event_remote_event_on_client_event(self, callback_data, callback_vtable) local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).OnClientEvent:Connect(function(...) local values_tuple = { ... }; @@ -11820,6 +11877,19 @@ function abi.ffi.event_remote_event_on_client_event(self, callback_data, callbac end)); return createPointer(result_0); end +function abi.ffi.event_remote_event_on_client_event_on_client_event_async(self, callback_data, callback_vtable, callback_poll) + local result_0 = createConnection(callback_data, callback_vtable, getPointer(self).OnClientEvent:Connect(function(...) + local values_tuple = { ... }; + local values_len = select("#", ...); + local values_tuple_vec = allocVec(values_len * 4) + for i = 1, values_len do + local values_tuple_vec_value = values_tuple[i]; + storeU32(memory, values_tuple_vec + (i - 1) * 4 + 0, createPointer(values_tuple_vec_value)); + end + invokeFunction(callback_data, callback_vtable, values_tuple_vec, values_len) + end)); + return createPointer(result_0); +end function abi.ffi.method_remote_event_fire_all_clients(self, values_addr, values_len) local values_vec = table.create(values_len); for i = 1, values_len do @@ -11844,7 +11914,25 @@ function abi.ffi.method_remote_event_fire_server(self, values_addr, values_len) end getPointer(self):FireServer(unpack(values_vec, 1, values_len)) end -function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, callback_vtable, callback_poll) +function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, callback_vtable) + getPointer(self).OnServerInvoke = function(player, ...) + local values_tuple = { ... }; + local values_len = select("#", ...); + local values_tuple_vec = allocVec(values_len * 4) + for i = 1, values_len do + local values_tuple_vec_value = values_tuple[i]; + storeU32(memory, values_tuple_vec + (i - 1) * 4 + 0, createPointer(values_tuple_vec_value)); + end + local result_0, result_1 = invokeFunction(callback_data, callback_vtable, createPointer(player), values_tuple_vec, values_len); + local callback_vec = table.create(result_1); + for i = 1, result_1 do + local vecElement_0 = loadU32(memory, result_0 + (i - 1) * 4 + 0) + callback_vec[i] = getPointer(vecElement_0); + end + return unpack(callback_vec, 1, result_1); + end; +end +function abi.ffi.callback_remote_function_on_server_invoke_on_server_invoke_async(self, callback_data, callback_vtable, callback_poll) getPointer(self).OnServerInvoke = function(player, ...) local values_tuple = { ... }; local values_len = select("#", ...); @@ -11862,7 +11950,25 @@ function abi.ffi.callback_remote_function_on_server_invoke(self, callback_data, return unpack(callback_vec, 1, result_1); end; end -function abi.ffi.callback_remote_function_on_client_invoke(self, callback_data, callback_vtable, callback_poll) +function abi.ffi.callback_remote_function_on_client_invoke(self, callback_data, callback_vtable) + getPointer(self).OnClientInvoke = function(...) + local values_tuple = { ... }; + local values_len = select("#", ...); + local values_tuple_vec = allocVec(values_len * 4) + for i = 1, values_len do + local values_tuple_vec_value = values_tuple[i]; + storeU32(memory, values_tuple_vec + (i - 1) * 4 + 0, createPointer(values_tuple_vec_value)); + end + local result_0, result_1 = invokeFunction(callback_data, callback_vtable, values_tuple_vec, values_len); + local callback_vec = table.create(result_1); + for i = 1, result_1 do + local vecElement_0 = loadU32(memory, result_0 + (i - 1) * 4 + 0) + callback_vec[i] = getPointer(vecElement_0); + end + return unpack(callback_vec, 1, result_1); + end; +end +function abi.ffi.callback_remote_function_on_client_invoke_on_client_invoke_async(self, callback_data, callback_vtable, callback_poll) getPointer(self).OnClientInvoke = function(...) local values_tuple = { ... }; local values_len = select("#", ...); @@ -15632,6 +15738,17 @@ function abi.ffi.static_function_internal_new_instance_new(class_name_addr, clas local result_0 = Instance.new(loadString(memory, class_name_addr, class_name_len)); return createPointer(result_0); end +function abi.ffi.static_function_internal_task_wait(time) + local future = createPointer(0); + task.spawn(function() + local result_0 = task.wait(time); + local output_addr = allocVec(8); + storeFloat(memory, output_addr + 0, result_0); + updatePointer(future, output_addr); + wakeFuture(future); + end) + return future; +end function abi.ffi.static_function_vector_3_new() local result_0 = Vector3.new(); return createPointer(result_0); diff --git a/src/conversion/impls.rs b/src/conversion/impls.rs deleted file mode 100644 index cbc8726..0000000 --- a/src/conversion/impls.rs +++ /dev/null @@ -1,58 +0,0 @@ -use super::{ - foreign, - structs::{RustOption, RustSlice, RustString}, - Foreign, FromForeign, IntoForeign, -}; - -impl IntoForeign for Option { - type Output = RustOption; - - fn into_foreign(self) -> Self::Output { - match self { - Some(value) => RustOption::Some(value.into_foreign()), - None => RustOption::None, - } - } -} - -impl FromForeign for Option { - type Input = RustOption; - - fn from_foreign(value: Self::Input) -> Self { - match value { - RustOption::Some(value) => Some(T::from_foreign(value)), - RustOption::None => None, - } - } -} - -impl FromForeign for String { - type Input = RustString; - - fn from_foreign(input: Self::Input) -> Self { - unsafe { String::from_raw_parts(input.content, input.length, input.length) } - } -} - -impl IntoForeign for &[T] { - type Output = RustSlice; - - fn into_foreign(self) -> Self::Output { - RustSlice { - content: self.as_ptr(), - length: self.len(), - } - } -} - -impl FromForeign for Vec { - type Input = RustSlice; - - fn from_foreign(input: Self::Input) -> Self {} -} - -// impl IntoForeign for &[T] { -// type Output = RustSlice; -// } - -foreign!(i8 u8 i16 u16 i32 u32 f32 i64 u64 f64 RustString RustSlice RustOption); From b673901a45065e59b62f5bc60621140f229fd9fa Mon Sep 17 00:00:00 2001 From: fireboltofdeath <24422634+Fireboltofdeath@users.noreply.github.com> Date: Fri, 23 Feb 2024 23:05:00 -0500 Subject: [PATCH 5/5] Add task lib functions to codegen --- crates/codegen/src/overrides.rs | 19 +++++++++++++++++++ crates/roblox-rs/examples/test.rs | 7 +------ crates/roblox-rs/src/libraries/task.rs | 21 ++++++--------------- roblox/abi.luau | 15 +++++++++++++++ 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/crates/codegen/src/overrides.rs b/crates/codegen/src/overrides.rs index 8d41341..b9c4d65 100644 --- a/crates/codegen/src/overrides.rs +++ b/crates/codegen/src/overrides.rs @@ -197,6 +197,25 @@ pub fn internal_namespace() -> PartialNamespace { ..MemberFlags::default() }; }, + member! { + task_spawn(StaticFunction(Some("task"), Some("spawn"))); + signature = ( + closure: CodegenKind::Function(vec![], Box::new(CodegenKind::Void), Async::No) + ) -> CodegenKind::Void; + }, + member! { + task_defer(StaticFunction(Some("task"), Some("defer"))); + signature = ( + closure: CodegenKind::Function(vec![], Box::new(CodegenKind::Void), Async::No) + ) -> CodegenKind::Void; + }, + member! { + task_delay(StaticFunction(Some("task"), Some("delay"))); + signature = ( + delay: number, + closure: CodegenKind::Function(vec![], Box::new(CodegenKind::Void), Async::No) + ) -> CodegenKind::Void; + }, ], } } diff --git a/crates/roblox-rs/examples/test.rs b/crates/roblox-rs/examples/test.rs index c62cec8..84f4a4a 100644 --- a/crates/roblox-rs/examples/test.rs +++ b/crates/roblox-rs/examples/test.rs @@ -3,13 +3,8 @@ use std::convert::TryFrom; use roblox_rs::{println, *}; -// Use `wee_alloc` as the global allocator. -// #[global_allocator] -// static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; - -/// # Safety #[allow(unreachable_code)] -pub fn main() { +fn main() { futures::spawn(async { loop { let time = task::wait(4.0).await; diff --git a/crates/roblox-rs/src/libraries/task.rs b/crates/roblox-rs/src/libraries/task.rs index d1e37dd..676d5bd 100644 --- a/crates/roblox-rs/src/libraries/task.rs +++ b/crates/roblox-rs/src/libraries/task.rs @@ -1,26 +1,17 @@ use crate::internal; -#[allow(improper_ctypes)] -extern "C" { - fn lib_task_delay(amount: f64, task: Box); - fn lib_task_defer(task: Box); - fn lib_task_spawn(task: Box); - // fn lib_task_wait(amount: f64) -> LuaFuture; +pub fn delay(amount: f64, value: F) { + internal::task_delay(amount, value) } -pub fn delay(amount: f64, value: F) { - unsafe { lib_task_delay(amount, Box::new(value)) } +pub fn defer(value: F) { + internal::task_defer(value) } -pub fn defer(value: F) { - unsafe { lib_task_defer(Box::new(value)) } -} - -pub fn spawn(value: F) { - unsafe { lib_task_spawn(Box::new(value)) } +pub fn spawn(value: F) { + internal::task_spawn(value) } pub async fn wait(amount: f64) -> f64 { - // unsafe { lib_task_wait(amount) } internal::task_wait(amount).await } diff --git a/roblox/abi.luau b/roblox/abi.luau index 1b53e2f..3539b98 100644 --- a/roblox/abi.luau +++ b/roblox/abi.luau @@ -15749,6 +15749,21 @@ function abi.ffi.static_function_internal_task_wait(time) end) return future; end +function abi.ffi.static_function_internal_task_spawn(closure_data, closure_vtable) + task.spawn(function() + invokeFunction(closure_data, closure_vtable) + end) +end +function abi.ffi.static_function_internal_task_defer(closure_data, closure_vtable) + task.defer(function() + invokeFunction(closure_data, closure_vtable) + end) +end +function abi.ffi.static_function_internal_task_delay(delay, closure_data, closure_vtable) + task.delay(delay, function() + invokeFunction(closure_data, closure_vtable) + end) +end function abi.ffi.static_function_vector_3_new() local result_0 = Vector3.new(); return createPointer(result_0);