diff --git a/Cargo.lock b/Cargo.lock index e6258738d43..aa9e00ebb2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7151,6 +7151,7 @@ dependencies = [ "insta", "itertools 0.12.1", "regex", + "serde_json", "spacetimedb-data-structures", "spacetimedb-lib 1.6.0", "spacetimedb-primitives 1.6.0", diff --git a/crates/cli/src/subcommands/generate.rs b/crates/cli/src/subcommands/generate.rs index f8da4eb731d..5fdd6c2c9a4 100644 --- a/crates/cli/src/subcommands/generate.rs +++ b/crates/cli/src/subcommands/generate.rs @@ -25,7 +25,7 @@ use std::io::Read; pub fn cli() -> clap::Command { clap::Command::new("generate") .about("Generate client files for a spacetime module.") - .override_usage("spacetime generate --lang --out-dir [--project-path | --bin-path | --module-name | --uproject-dir ]") + .override_usage("spacetime generate --lang --out-dir [--project-path | --bin-path | --module-name | --uproject-dir | --module-prefix ]") .arg( Arg::new("wasm_file") .value_parser(clap::value_parser!(PathBuf)) @@ -93,6 +93,11 @@ pub fn cli() -> clap::Command { .help("The module name that should be used for DLL export macros (required for lang unrealcpp)") .required_if_eq("lang", "unrealcpp") ) + .arg( + Arg::new("module_prefix") + .long("module-prefix") + .help("The module prefix to use for generated types (only used with --lang unrealcpp)") + ) .arg( Arg::new("lang") .required(true) @@ -135,6 +140,7 @@ pub async fn exec_ex( let lang = *args.get_one::("lang").unwrap(); let namespace = args.get_one::("namespace").unwrap(); let module_name = args.get_one::("module_name"); + let module_prefix = args.get_one::("module_prefix"); let force = args.get_flag("force"); let build_options = args.get_one::("build_options").unwrap(); @@ -186,6 +192,7 @@ pub async fn exec_ex( unreal_cpp_lang = UnrealCpp { module_name: module_name.as_ref().unwrap(), uproject_dir: out_dir, + module_prefix: module_prefix.as_ref().map(|s| s.as_str()).unwrap_or(""), }; &unreal_cpp_lang as &dyn Lang } diff --git a/crates/codegen/Cargo.toml b/crates/codegen/Cargo.toml index 54e0f589669..9d362a09ade 100644 --- a/crates/codegen/Cargo.toml +++ b/crates/codegen/Cargo.toml @@ -15,6 +15,7 @@ spacetimedb-schema.workspace = true anyhow.workspace = true convert_case.workspace = true itertools.workspace = true +serde_json.workspace = true [dev-dependencies] fs-err.workspace = true diff --git a/crates/codegen/src/unrealcpp.rs b/crates/codegen/src/unrealcpp.rs index 35ec3baecd7..a67f34e03b5 100644 --- a/crates/codegen/src/unrealcpp.rs +++ b/crates/codegen/src/unrealcpp.rs @@ -1,8 +1,6 @@ //! Autogenerated Unreal‑C++ code‑gen backend for SpacetimeDB CLI use crate::code_indenter::CodeIndenter; -use crate::util::{ - collect_case, fmt_fn, iter_tables, print_auto_generated_file_comment, print_auto_generated_version_comment, -}; +use crate::util::{fmt_fn, iter_tables, print_auto_generated_file_comment, print_auto_generated_version_comment}; use crate::util::{iter_indexes, iter_reducers}; use crate::Lang; use crate::OutputFile; @@ -23,6 +21,7 @@ use std::path::Path; pub struct UnrealCpp<'opts> { pub module_name: &'opts str, pub uproject_dir: &'opts Path, + pub module_prefix: &'opts str, } // --------------------------------------------------------------------------- @@ -37,9 +36,9 @@ impl UnrealCpp<'_> { impl Lang for UnrealCpp<'_> { fn generate_table_file(&self, module: &ModuleDef, table: &TableDef) -> OutputFile { - let struct_name = type_ref_name(module, table.product_type_ref); + let module_prefix = self.module_prefix; + let struct_name = type_ref_name(module_prefix, module, table.product_type_ref); let self_header = struct_name.clone() + "Table"; - let mut output = UnrealCppAutogen::new( &[ "Types/Builtins.h", @@ -78,7 +77,8 @@ impl Lang for UnrealCpp<'_> { if let Some(col) = columns.as_singleton() { let (f_name, f_ty) = &product_type.unwrap().elements[col.idx()]; let field_name = f_name.deref().to_case(Case::Pascal); - let field_type = cpp_ty_fmt_with_module(module, f_ty, self.module_name).to_string(); + let field_type = + cpp_ty_fmt_with_module(self.module_prefix, module, f_ty, self.module_name).to_string(); let index_name = accessor_name.deref().to_case(Case::Pascal); let index_class_name = format!("U{table_pascal}{index_name}UniqueIndex"); let key_type = field_type.clone(); @@ -175,7 +175,8 @@ impl Lang for UnrealCpp<'_> { .map(|col| { let (f_name, f_ty) = &product_type.unwrap().elements[col.idx()]; let field_name = f_name.deref().to_case(Case::Pascal); - let field_type = cpp_ty_fmt_with_module(module, f_ty, self.module_name).to_string(); + let field_type = + cpp_ty_fmt_with_module(self.module_prefix, module, f_ty, self.module_name).to_string(); let param_type = format!("const {field_type}&"); (field_name, field_type, param_type, f_ty, f_name.deref().to_string()) @@ -329,20 +330,20 @@ impl Lang for UnrealCpp<'_> { writeln!(output, " // Table Events"); writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( "); writeln!(output, " FOn{table_pascal}Insert,"); - writeln!(output, " const FEventContext&, Context,"); + writeln!(output, " const F{module_prefix}EventContext&, Context,"); writeln!(output, " const {row_struct}&, NewRow);"); writeln!(output); writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( "); writeln!(output, " FOn{table_pascal}Update,"); - writeln!(output, " const FEventContext&, Context,"); + writeln!(output, " const F{module_prefix}EventContext&, Context,"); writeln!(output, " const {row_struct}&, OldRow,"); writeln!(output, " const {row_struct}&, NewRow);"); writeln!(output); writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( "); writeln!(output, " FOn{table_pascal}Delete,"); - writeln!(output, " const FEventContext&, Context,"); + writeln!(output, " const F{module_prefix}EventContext&, Context,"); writeln!(output, " const {row_struct}&, DeletedRow);"); writeln!(output); @@ -378,49 +379,56 @@ impl Lang for UnrealCpp<'_> { filename: format!( "Source/{}/Public/ModuleBindings/Tables/{}Table.g.h", self.module_name, - type_ref_name(module, table.product_type_ref) + type_ref_name(self.module_prefix, module, table.product_type_ref) ), code: output.into_inner(), } } fn generate_type_files(&self, module: &ModuleDef, typ: &TypeDef) -> Vec { - let name = typ - .name - .name_segments() - .last() - .map(|id| id.deref()) - .unwrap_or("Unnamed"); + let name = type_ref_name(self.module_prefix, module, typ.ty); + let filename = format!( "Source/{}/Public/ModuleBindings/Types/{}Type.g.h", - self.module_name, - collect_case(Case::Pascal, typ.name.name_segments()) + self.module_name, &name ); let code: String = match &module.typespace_for_generate()[typ.ty] { - AlgebraicTypeDef::PlainEnum(plain_enum) => autogen_cpp_enum(name, plain_enum), - AlgebraicTypeDef::Product(product_type_def) => { - autogen_cpp_struct(module, name, product_type_def, &self.get_api_macro(), self.module_name) - } - AlgebraicTypeDef::Sum(sum_type_def) => { - autogen_cpp_sum(module, name, sum_type_def, &self.get_api_macro(), self.module_name) - } + AlgebraicTypeDef::PlainEnum(plain_enum) => autogen_cpp_enum(&name, plain_enum), + AlgebraicTypeDef::Product(product_type_def) => autogen_cpp_struct( + self.module_prefix, + module, + &name, + product_type_def, + &self.get_api_macro(), + self.module_name, + ), + AlgebraicTypeDef::Sum(sum_type_def) => autogen_cpp_sum( + self.module_prefix, + module, + &name, + sum_type_def, + &self.get_api_macro(), + self.module_name, + ), }; vec![OutputFile { filename, code }] } fn generate_reducer_file(&self, module: &ModuleDef, reducer: &ReducerDef) -> OutputFile { - let reducer_snake = reducer.name.deref(); - let pascal = reducer_snake.to_case(Case::Pascal); + let reducer_original = reducer.name.deref(); + let reducer_pascal = reducer_original.to_case(Case::Pascal); + let module_prefix = self.module_prefix; + let pascal = format!("{module_prefix}{reducer_pascal}"); // Collect includes for parameter types let mut includes = HashSet::::new(); for (_param_name, param_type) in &reducer.params_for_generate.elements { - collect_includes_for_type(module, param_type, &mut includes, self.module_name); + collect_includes_for_type(module_prefix, module, param_type, &mut includes, self.module_name); } // Add ReducerBase.g.h for UReducerBase definition - includes.insert("ModuleBindings/ReducerBase.g.h".to_string()); + includes.insert(format!("ModuleBindings/{module_prefix}ReducerBase.g.h")); // Convert to sorted vector let mut include_vec: Vec = includes.into_iter().collect(); @@ -444,7 +452,7 @@ impl Lang for UnrealCpp<'_> { // Generate properties for each parameter for (param_name, param_type) in &reducer.params_for_generate.elements { let param_pascal = param_name.deref().to_case(Case::Pascal); - let type_str = cpp_ty_fmt_with_module(module, param_type, self.module_name).to_string(); + let type_str = cpp_ty_fmt_with_module(self.module_prefix, module, param_type, self.module_name).to_string(); let field_decl = format!("{type_str} {param_pascal}"); // Check if the type is blueprintable @@ -475,7 +483,8 @@ impl Lang for UnrealCpp<'_> { } first = false; let param_pascal = param_name.deref().to_case(Case::Pascal); - let type_str = cpp_ty_fmt_with_module(module, param_type, self.module_name).to_string(); + let type_str = + cpp_ty_fmt_with_module(self.module_prefix, module, param_type, self.module_name).to_string(); write!(header, "const {type_str}& In{param_pascal}"); } @@ -561,7 +570,7 @@ impl Lang for UnrealCpp<'_> { writeln!(header, "UCLASS(BlueprintType)"); writeln!( header, - "class {} U{pascal}Reducer : public UReducerBase", + "class {} U{pascal}Reducer : public U{module_prefix}ReducerBase", self.get_api_macro() ); writeln!(header, "{{"); @@ -572,7 +581,7 @@ impl Lang for UnrealCpp<'_> { // Generate properties for each parameter (for dispatching) for (param_name, param_type) in &reducer.params_for_generate.elements { let param_pascal = param_name.deref().to_case(Case::Pascal); - let type_str = cpp_ty_fmt_with_module(module, param_type, self.module_name).to_string(); + let type_str = cpp_ty_fmt_with_module(self.module_prefix, module, param_type, self.module_name).to_string(); let field_decl = format!("{type_str} {param_pascal}"); // Check if the type is blueprintable @@ -605,16 +614,54 @@ impl Lang for UnrealCpp<'_> { fn generate_global_files(&self, module: &ModuleDef) -> Vec { let mut files: Vec = vec![]; + let module_prefix = self.module_prefix; + + // First, we need to confirm this module has the required base files + // Unreal works on the idea of modules added to the .uproject Source folder and described in the .uproject file + // To have the module build these files must exist + let source_dir = self.uproject_dir.join("Source").join(self.module_name); + let required_files = [ + ( + format!("{}.Build.cs", self.module_name), + generate_build_cs_content(self.module_name), + ), + ( + format!("{}.cpp", self.module_name), + generate_module_cpp_content(self.module_name), + ), + ( + format!("{}.h", self.module_name), + generate_module_h_content(self.module_name), + ), + ]; + + for (filename, content) in required_files { + let file_path = source_dir.join(&filename); + if !file_path.exists() { + files.push(OutputFile { + filename: format!("Source/{}/{}", self.module_name, filename), + code: content, + }); + } + } + // We also need to ensure the .uproject file includes this module + let _ = ensure_module_in_uproject(self.uproject_dir, self.module_name); - // First, collect and generate all optional types - let optional_types = collect_optional_types(module); + // Second, collect and generate all optional types + let optional_types = collect_optional_types(self.module_prefix, module); for optional_name in optional_types { let module_name = &self.module_name; let module_name_pascal = module_name.to_case(Case::Pascal); let filename = format!("Source/{module_name}/Public/ModuleBindings/Optionals/{module_name_pascal}{optional_name}.g.h"); - let content = generate_optional_type(&optional_name, module, &self.get_api_macro(), self.module_name); + let content = generate_optional_type( + &optional_name, + self.module_prefix, + module, + &self.get_api_macro(), + self.module_name, + ); files.push(OutputFile { filename, code: content, @@ -630,25 +677,38 @@ impl Lang for UnrealCpp<'_> { includes.insert("Connection/Subscription.h".to_string()); includes.insert("Connection/SetReducerFlags.h".to_string()); includes.insert("Connection/Callback.h".to_string()); - includes.insert("ModuleBindings/ReducerBase.g.h".to_string()); + includes.insert(format!("ModuleBindings/{module_prefix}ReducerBase.g.h")); includes.insert("Kismet/BlueprintFunctionLibrary.h".to_string()); // Include reducers for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{}", reducer.name.deref().to_case(Case::Pascal)); + includes.insert(format!("ModuleBindings/Reducers/{reducer_pascal}.g.h")); } // Collect includes for types used in delegates and contexts - // FSpacetimeDBIdentity is used in FOnConnectDelegate and context methods - collect_includes_for_type(module, &AlgebraicTypeUse::Identity, &mut includes, self.module_name); + // FSpacetimeDBIdentity is used in F{module_prefix}OnConnectDelegate and context methods + collect_includes_for_type( + self.module_prefix, + module, + &AlgebraicTypeUse::Identity, + &mut includes, + self.module_name, + ); // FSpacetimeDBConnectionId is used in context methods - collect_includes_for_type(module, &AlgebraicTypeUse::ConnectionId, &mut includes, self.module_name); + collect_includes_for_type( + self.module_prefix, + module, + &AlgebraicTypeUse::ConnectionId, + &mut includes, + self.module_name, + ); // Collect includes for all reducer parameter types for reducer in iter_reducers(module) { for (_param_name, param_type) in &reducer.params_for_generate.elements { - collect_includes_for_type(module, param_type, &mut includes, self.module_name); + collect_includes_for_type(module_prefix, module, param_type, &mut includes, self.module_name); } } @@ -659,31 +719,33 @@ impl Lang for UnrealCpp<'_> { // Convert to string references let include_refs: Vec<&str> = include_vec.iter().map(|s| s.as_str()).collect(); - let mut client_h = UnrealCppAutogen::new(&include_refs, "SpacetimeDBClient", true); + let self_header = format!("{module_prefix}SpacetimeDBClient"); + let mut client_h = UnrealCppAutogen::new(&include_refs, self_header.as_str(), true); // Forward declarations writeln!(client_h, "// Forward declarations"); - writeln!(client_h, "class UDbConnection;"); - writeln!(client_h, "class URemoteTables;"); - writeln!(client_h, "class URemoteReducers;"); - writeln!(client_h, "class USubscriptionBuilder;"); - writeln!(client_h, "class USubscriptionHandle;"); + writeln!(client_h, "class U{module_prefix}DbConnection;"); + writeln!(client_h, "class U{module_prefix}RemoteTables;"); + writeln!(client_h, "class U{module_prefix}RemoteReducers;"); + writeln!(client_h, "class U{module_prefix}SubscriptionBuilder;"); + writeln!(client_h, "class U{module_prefix}SubscriptionHandle;"); writeln!(client_h); writeln!(client_h, "/** Forward declaration for tables */"); for table in iter_tables(module) { - let table_pascal = type_ref_name(module, table.product_type_ref); + let table_pascal = type_ref_name(module_prefix, module, table.product_type_ref); writeln!(client_h, "class U{table_pascal}Table;"); } writeln!(client_h, "/***/"); writeln!(client_h); // Delegates first (as in manual) - generate_delegates(&mut client_h); + generate_delegates(&mut client_h, module_prefix); // Context structs generate_context_structs( &mut client_h, + self.module_prefix, module, &self.get_api_macro(), &self.module_name.to_case(Case::Pascal), @@ -693,7 +755,7 @@ impl Lang for UnrealCpp<'_> { writeln!(client_h, "UCLASS(BlueprintType)"); writeln!( client_h, - "class {} USetReducerFlags : public USetReducerFlagsBase", + "class {} U{module_prefix}SetReducerFlags : public USetReducerFlagsBase", self.get_api_macro() ); writeln!(client_h, "{{"); @@ -702,9 +764,9 @@ impl Lang for UnrealCpp<'_> { writeln!(client_h, "public:"); for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); writeln!(client_h, "\tUFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); - writeln!(client_h, "\tvoid {reducer_pascal}(ECallReducerFlags Flag);"); + writeln!(client_h, "\tvoid {reducer_name}(ECallReducerFlags Flag);"); } writeln!(client_h); @@ -712,50 +774,69 @@ impl Lang for UnrealCpp<'_> { writeln!(client_h); // RemoteTables class - generate_remote_tables_class(&mut client_h, module, &self.get_api_macro()); + generate_remote_tables_class(&mut client_h, module_prefix, module, &self.get_api_macro()); // RemoteReducers class - generate_remote_reducers_class(&mut client_h, module, &self.get_api_macro(), self.module_name); + generate_remote_reducers_class( + &mut client_h, + module_prefix, + module, + &self.get_api_macro(), + self.module_name, + ); // SubscriptionBuilder class - generate_subscription_builder_class(&mut client_h, &self.get_api_macro()); + generate_subscription_builder_class(&mut client_h, module_prefix, &self.get_api_macro()); // SubscriptionHandle class - generate_subscription_handle_class(&mut client_h, &self.get_api_macro()); + generate_subscription_handle_class(&mut client_h, module_prefix, &self.get_api_macro()); // DbConnectionBuilder class - generate_db_connection_builder_class(&mut client_h, &self.get_api_macro()); + generate_db_connection_builder_class(&mut client_h, module_prefix, &self.get_api_macro()); // Main DbConnection class - generate_db_connection_class(&mut client_h, module, &self.get_api_macro()); + generate_db_connection_class( + &mut client_h, + module_prefix, + module, + &self.get_api_macro(), + self.module_name, + ); // Generate the separate ReducerBase file - let mut reducer_base_header = UnrealCppAutogen::new(&[], "ReducerBase", false); + let reducer_base_header_name = format!("{module_prefix}ReducerBase"); + let mut reducer_base_header = UnrealCppAutogen::new(&[], reducer_base_header_name.as_str(), false); // Generate the UReducerBase class writeln!(reducer_base_header, "// Abstract Reducer base class"); writeln!(reducer_base_header, "UCLASS(Abstract, BlueprintType)"); writeln!( reducer_base_header, - "class {} UReducerBase : public UObject", + "class {} U{module_prefix}ReducerBase : public UObject", self.get_api_macro() ); writeln!(reducer_base_header, "{{"); writeln!(reducer_base_header, " GENERATED_BODY()"); writeln!(reducer_base_header); writeln!(reducer_base_header, "public:"); - writeln!(reducer_base_header, " virtual ~UReducerBase() = default;"); + writeln!( + reducer_base_header, + " virtual ~U{module_prefix}ReducerBase() = default;" + ); writeln!(reducer_base_header, "}};"); writeln!(reducer_base_header); files.push(OutputFile { - filename: format!("Source/{}/Public/ModuleBindings/ReducerBase.g.h", self.module_name), + filename: format!( + "Source/{}/Public/ModuleBindings/{module_prefix}ReducerBase.g.h", + self.module_name + ), code: reducer_base_header.into_inner(), }); files.push(OutputFile { filename: format!( - "Source/{}/Public/ModuleBindings/SpacetimeDBClient.g.h", + "Source/{}/Public/ModuleBindings/{module_prefix}SpacetimeDBClient.g.h", self.module_name ), code: client_h.into_inner(), @@ -767,13 +848,14 @@ impl Lang for UnrealCpp<'_> { .map(|table| { format!( "ModuleBindings/Tables/{}Table.g.h", - type_ref_name(module, table.product_type_ref) + type_ref_name(self.module_prefix, module, table.product_type_ref) ) }) .collect(); let table_includes_str: Vec<&str> = table_includes.iter().map(|s| s.as_str()).collect(); - let mut cpp_includes = vec!["ModuleBindings/SpacetimeDBClient.g.h"]; + let spacetime_include = format!("ModuleBindings/{module_prefix}SpacetimeDBClient.g.h"); + let mut cpp_includes = vec![spacetime_include.as_str()]; // Add additional includes from manual reference cpp_includes.extend_from_slice(&["DBCache/WithBsatn.h", "BSATN/UEBSATNHelpers.h"]); @@ -782,10 +864,10 @@ impl Lang for UnrealCpp<'_> { cpp_includes.extend(table_includes_str); let mut client_cpp = UnrealCppAutogen::new_cpp(&cpp_includes); - generate_client_implementation(&mut client_cpp, module, self.module_name); + generate_client_implementation(&mut client_cpp, module_prefix, module, self.module_name); files.push(OutputFile { filename: format!( - "Source/{}/Private/ModuleBindings/SpacetimeDBClient.g.cpp", + "Source/{}/Private/ModuleBindings/{module_prefix}SpacetimeDBClient.g.cpp", self.module_name ), code: client_cpp.into_inner(), @@ -793,11 +875,11 @@ impl Lang for UnrealCpp<'_> { // Generate .cpp implementation files for each table for table in module.tables() { - let table_cpp_content = generate_table_cpp(module, table, self.module_name); + let table_cpp_content = generate_table_cpp(module_prefix, module, table, self.module_name); let table_cpp_filename = format!( "Source/{}/Private/ModuleBindings/Tables/{}Table.g.cpp", self.module_name, - type_ref_name(module, table.product_type_ref) + type_ref_name(module_prefix, module, table.product_type_ref) ); files.push(OutputFile { filename: table_cpp_filename, @@ -810,8 +892,8 @@ impl Lang for UnrealCpp<'_> { } // Helper function to generate table .cpp implementation files -fn generate_table_cpp(module: &ModuleDef, table: &TableDef, module_name: &str) -> String { - let table_pascal = type_ref_name(module, table.product_type_ref); +fn generate_table_cpp(module_prefix: &str, module: &ModuleDef, table: &TableDef, module_name: &str) -> String { + let table_pascal = type_ref_name(module_prefix, module, table.product_type_ref); let row_struct = format!("F{table_pascal}Type"); // Include the table header and other necessary headers @@ -845,7 +927,7 @@ fn generate_table_cpp(module: &ModuleDef, table: &TableDef, module_name: &str) - if let Some(col) = columns.as_singleton() { let (f_name, f_ty) = &product_type.unwrap().elements[col.idx()]; let _field_name = f_name.deref().to_case(Case::Pascal); - let field_type = cpp_ty_fmt_with_module(module, f_ty, module_name).to_string(); + let field_type = cpp_ty_fmt_with_module(module_prefix, module, f_ty, module_name).to_string(); let index_name = accessor_name.deref().to_case(Case::Pascal); unique_indexes.push((index_name, field_type, f_name.deref().to_string())); } @@ -860,7 +942,7 @@ fn generate_table_cpp(module: &ModuleDef, table: &TableDef, module_name: &str) - .map(|col| { let (f_name, f_ty) = &product_type.unwrap().elements[col.idx()]; let field_name = f_name.deref().to_case(Case::Pascal); - let field_type = cpp_ty_fmt_with_module(module, f_ty, module_name).to_string(); + let field_type = cpp_ty_fmt_with_module(module_prefix, module, f_ty, module_name).to_string(); (field_name, field_type) }) .collect(); @@ -957,7 +1039,7 @@ fn generate_table_cpp(module: &ModuleDef, table: &TableDef, module_name: &str) - if let Some(pk) = schema.pk() { let pk_field_name = pk.col_name.deref().to_case(Case::Pascal); let pk_type = &product_type.unwrap().elements[pk.col_pos.idx()].1; - let pk_type_str = cpp_ty_fmt_with_module(module, pk_type, module_name).to_string(); + let pk_type_str = cpp_ty_fmt_with_module(module_prefix, module, pk_type, module_name).to_string(); writeln!(output, " Diff.DeriveUpdatesByPrimaryKey<{pk_type_str}>("); writeln!(output, " [](const {row_struct}& Row) "); writeln!(output, " {{"); @@ -1001,7 +1083,7 @@ fn generate_table_cpp(module: &ModuleDef, table: &TableDef, module_name: &str) - // Helper functions for generating the consolidated SpacetimeDBClient file -fn generate_delegates(output: &mut UnrealCppAutogen) { +fn generate_delegates(output: &mut UnrealCppAutogen, module_prefix: &str) { writeln!( output, "// Delegates using the generated connection type. These wrap the base" @@ -1010,43 +1092,55 @@ fn generate_delegates(output: &mut UnrealCppAutogen) { output, "// delegates defined in the SDK so that projects can work directly with" ); - writeln!(output, "// UDbConnection without manual casting in user code."); + writeln!( + output, + "// U{module_prefix}DbConnection without manual casting in user code." + ); writeln!(output, "DECLARE_DYNAMIC_DELEGATE_ThreeParams("); - writeln!(output, "\tFOnConnectDelegate,"); - writeln!(output, "\tUDbConnection*, Connection,"); + writeln!(output, "\tF{module_prefix}OnConnectDelegate,"); + writeln!(output, "\tU{module_prefix}DbConnection*, Connection,"); writeln!(output, "\tFSpacetimeDBIdentity, Identity,"); writeln!(output, "\tconst FString&, Token);"); writeln!(output); writeln!(output, "DECLARE_DYNAMIC_DELEGATE_TwoParams("); - writeln!(output, "\tFOnDisconnectDelegate,"); - writeln!(output, "\tUDbConnection*, Connection,"); + writeln!(output, "\tF{module_prefix}OnDisconnectDelegate,"); + writeln!(output, "\tU{module_prefix}DbConnection*, Connection,"); writeln!(output, "\tconst FString&, Error);"); writeln!(output); writeln!(output); } -fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, api_macro: &str, module_name: &str) { +fn generate_context_structs( + output: &mut UnrealCppAutogen, + module_prefix: &str, + module: &ModuleDef, + api_macro: &str, + module_name: &str, +) { writeln!(output, "// Context classes for event handling"); writeln!(output); writeln!(output, "USTRUCT(BlueprintType)"); - writeln!(output, "struct {api_macro} FContextBase"); + writeln!(output, "struct {api_macro} F{module_prefix}ContextBase"); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); writeln!(output); writeln!( output, - "\tFContextBase() : Db(nullptr), Reducers(nullptr), SetReducerFlags(nullptr), Conn(nullptr) {{}};" + "\tF{module_prefix}ContextBase() : Db(nullptr), Reducers(nullptr), SetReducerFlags(nullptr), Conn(nullptr) {{}};" + ); + writeln!( + output, + "\tF{module_prefix}ContextBase(U{module_prefix}DbConnection* InConn);" ); - writeln!(output, "\tFContextBase(UDbConnection* InConn);"); writeln!(output); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category = \"SpacetimeDB\")"); - writeln!(output, "\tURemoteTables* Db;"); + writeln!(output, "\tU{module_prefix}RemoteTables* Db;"); writeln!(output); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category = \"SpacetimeDB\")"); - writeln!(output, "\tURemoteReducers* Reducers;"); + writeln!(output, "\tU{module_prefix}RemoteReducers* Reducers;"); writeln!(output); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category = \"SpacetimeDB\")"); - writeln!(output, "\tUSetReducerFlags* SetReducerFlags;"); + writeln!(output, "\tU{module_prefix}SetReducerFlags* SetReducerFlags;"); writeln!(output); writeln!(output, "\tbool IsActive() const;"); writeln!(output, "\tvoid Disconnect();"); @@ -1055,11 +1149,11 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a "\tbool TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const;" ); writeln!(output, "\tFSpacetimeDBConnectionId GetConnectionId() const;"); - writeln!(output, "\tUSubscriptionBuilder* SubscriptionBuilder();"); + writeln!(output, "\tU{module_prefix}SubscriptionBuilder* SubscriptionBuilder();"); writeln!(output); writeln!(output, "protected:"); writeln!(output, "\tUPROPERTY()"); - writeln!(output, "\tUDbConnection* Conn;"); + writeln!(output, "\tU{module_prefix}DbConnection* Conn;"); writeln!(output); writeln!(output, "}};"); writeln!(output); @@ -1068,7 +1162,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "UCLASS()"); writeln!( output, - "class {api_macro} UContextBaseBpLib : public UBlueprintFunctionLibrary" + "class {api_macro} U{module_prefix}ContextBaseBpLib : public UBlueprintFunctionLibrary" ); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); @@ -1078,25 +1172,25 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "\tUFUNCTION(BlueprintPure, Category=\"SpacetimeDB\")"); writeln!( output, - "\tstatic URemoteTables* GetDb(const FContextBase& Ctx) {{ return Ctx.Db; }}" + "\tstatic U{module_prefix}RemoteTables* GetDb(const F{module_prefix}ContextBase& Ctx) {{ return Ctx.Db; }}" ); writeln!(output); writeln!(output, "\tUFUNCTION(BlueprintPure, Category=\"SpacetimeDB\")"); writeln!( output, - "\tstatic URemoteReducers* GetReducers(const FContextBase& Ctx) {{ return Ctx.Reducers; }}" + "\tstatic U{module_prefix}RemoteReducers* GetReducers(const F{module_prefix}ContextBase& Ctx) {{ return Ctx.Reducers; }}" ); writeln!(output); writeln!(output, "\tUFUNCTION(BlueprintPure, Category=\"SpacetimeDB\")"); writeln!( output, - "\tstatic USetReducerFlags* GetSetReducerFlags(const FContextBase& Ctx) {{ return Ctx.SetReducerFlags; }}" + "\tstatic U{module_prefix}SetReducerFlags* GetSetReducerFlags(const F{module_prefix}ContextBase& Ctx) {{ return Ctx.SetReducerFlags; }}" ); writeln!(output); writeln!(output, "\tUFUNCTION(BlueprintPure, Category=\"SpacetimeDB\")"); writeln!( output, - "\tstatic bool IsActive(const FContextBase& Ctx) {{ return Ctx.IsActive(); }}" + "\tstatic bool IsActive(const F{module_prefix}ContextBase& Ctx) {{ return Ctx.IsActive(); }}" ); writeln!(output, "}};"); @@ -1106,18 +1200,19 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a // Per-module typed Reducer tagged union + typed Event // --------------------------------------------------------------------- writeln!(output, "UENUM(BlueprintType, Category = \"SpacetimeDB\")"); - writeln!(output, "enum class EReducerTag : uint8"); + writeln!(output, "enum class E{module_prefix}ReducerTag : uint8"); writeln!(output, "{{"); { let mut first = true; for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + if !first { writeln!(output, ","); } else { first = false; } - write!(output, " {reducer_pascal}"); + write!(output, " {reducer_name}"); } writeln!(output); } @@ -1126,19 +1221,22 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a // FReducer: tagged union over reducer args, with optional metadata writeln!(output, "USTRUCT(BlueprintType)"); - writeln!(output, "struct {api_macro} FReducer"); + writeln!(output, "struct {api_macro} F{module_prefix}Reducer"); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output); writeln!(output, "public:"); writeln!(output, " UPROPERTY(BlueprintReadOnly, Category = \"SpacetimeDB\")"); - writeln!(output, " EReducerTag Tag = static_cast(0);"); + writeln!( + output, + " E{module_prefix}ReducerTag Tag = static_cast(0);" + ); writeln!(output); write!(output, " TVariant<"); { let mut first = true; for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{}", reducer.name.deref().to_case(Case::Pascal)); if !first { write!(output, ", "); } else { @@ -1158,14 +1256,16 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a // Static constructors, Is*, GetAs* for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{reducer_name}"); + writeln!( output, - " static FReducer {reducer_pascal}(const F{reducer_pascal}Args& Value)" + " static F{module_prefix}Reducer {reducer_name}(const F{reducer_pascal}Args& Value)" ); writeln!(output, " {{"); - writeln!(output, " FReducer Out;"); - writeln!(output, " Out.Tag = EReducerTag::{reducer_pascal};"); + writeln!(output, " F{module_prefix}Reducer Out;"); + writeln!(output, " Out.Tag = E{module_prefix}ReducerTag::{reducer_name};"); writeln!(output, " Out.Data.Set(Value);"); writeln!(output, " Out.ReducerName = TEXT(\"{}\");", reducer.name.deref()); writeln!(output, " return Out;"); @@ -1173,32 +1273,35 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output); writeln!( output, - " FORCEINLINE bool Is{reducer_pascal}() const {{ return Tag == EReducerTag::{reducer_pascal}; }}" + " FORCEINLINE bool Is{reducer_name}() const {{ return Tag == E{module_prefix}ReducerTag::{reducer_name}; }}" ); writeln!( output, - " FORCEINLINE F{reducer_pascal}Args GetAs{reducer_pascal}() const" + " FORCEINLINE F{reducer_pascal}Args GetAs{reducer_name}() const" ); writeln!(output, " {{"); writeln!( output, - " ensureMsgf(Is{reducer_pascal}(), TEXT(\"Reducer does not hold {reducer_pascal}!\"));" + " ensureMsgf(Is{reducer_name}(), TEXT(\"Reducer does not hold {reducer_name}!\"));" ); writeln!(output, " return Data.Get();"); writeln!(output, " }}"); writeln!(output); } - writeln!(output, " FORCEINLINE bool operator==(const FReducer& Other) const"); + writeln!( + output, + " FORCEINLINE bool operator==(const F{module_prefix}Reducer& Other) const" + ); writeln!(output, " {{"); writeln!(output, " if (Tag != Other.Tag || ReducerId != Other.ReducerId || RequestId != Other.RequestId || ReducerName != Other.ReducerName) return false;"); writeln!(output, " switch (Tag)"); writeln!(output, " {{"); for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); - writeln!(output, " case EReducerTag::{reducer_pascal}:"); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + writeln!(output, " case E{module_prefix}ReducerTag::{reducer_name}:"); writeln!( output, - " return GetAs{reducer_pascal}() == Other.GetAs{reducer_pascal}();" + " return GetAs{reducer_name}() == Other.GetAs{reducer_name}();" ); } writeln!(output, " default: return false;"); @@ -1206,7 +1309,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, " }}"); writeln!( output, - " FORCEINLINE bool operator!=(const FReducer& Other) const {{ return !(*this == Other); }}" + " FORCEINLINE bool operator!=(const F{module_prefix}Reducer& Other) const {{ return !(*this == Other); }}" ); writeln!(output, "}};"); writeln!(output); @@ -1215,7 +1318,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "UCLASS()"); writeln!( output, - "class {api_macro} UReducerBpLib : public UBlueprintFunctionLibrary" + "class {api_macro} U{module_prefix}ReducerBpLib : public UBlueprintFunctionLibrary" ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); @@ -1223,7 +1326,9 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "private:"); for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{reducer_name}"); + // ---- Static constructors ---- writeln!(output); writeln!( @@ -1232,9 +1337,9 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a ); writeln!( output, - " static FReducer {reducer_pascal}(const F{reducer_pascal}Args& Value) {{" + " static F{module_prefix}Reducer {reducer_name}(const F{reducer_pascal}Args& Value) {{" ); - writeln!(output, " return FReducer::{reducer_pascal}(Value);"); + writeln!(output, " return F{module_prefix}Reducer::{reducer_name}(Value);"); writeln!(output, " }}"); writeln!(output); @@ -1245,7 +1350,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a ); writeln!( output, - " static bool Is{reducer_pascal}(const FReducer& Reducer) {{ return Reducer.Is{reducer_pascal}(); }}" + " static bool Is{reducer_name}(const F{module_prefix}Reducer& Reducer) {{ return Reducer.Is{reducer_name}(); }}" ); writeln!(output); @@ -1256,9 +1361,9 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a ); writeln!( output, - " static F{reducer_pascal}Args GetAs{reducer_pascal}(const FReducer& Reducer) {{" + " static F{reducer_pascal}Args GetAs{reducer_name}(const F{module_prefix}Reducer& Reducer) {{" ); - writeln!(output, " return Reducer.GetAs{reducer_pascal}();"); + writeln!(output, " return Reducer.GetAs{reducer_name}();"); writeln!(output, " }}"); } @@ -1318,7 +1423,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a output, "\tUPROPERTY(EditAnywhere, BlueprintReadWrite, Category=\"SpacetimeDB\")" ); - writeln!(output, "\tFReducer Reducer;"); + writeln!(output, "\tF{module_prefix}Reducer Reducer;"); writeln!(output); writeln!( @@ -1357,7 +1462,10 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a output, "\t/** Tagged union holding reducer call, unit events, or error string */" ); - writeln!(output, "\tTVariant MessageData;"); + writeln!( + output, + "\tTVariant MessageData;" + ); writeln!(output); writeln!(output, "\t/** Type tag indicating what this event represents */"); @@ -1370,11 +1478,14 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a // === Static factory methods === writeln!(output, "\t/** === Static factory methods ===*/"); - writeln!(output, "\tstatic F{module_name}Event Reducer(const FReducer& Value)"); + writeln!( + output, + "\tstatic F{module_name}Event Reducer(const F{module_prefix}Reducer& Value)" + ); writeln!(output, "\t{{"); writeln!(output, "\t\tF{module_name}Event Obj;"); writeln!(output, "\t\tObj.Tag = ESpacetimeDBEventTag::Reducer;"); - writeln!(output, "\t\tObj.MessageData.Set(Value);"); + writeln!(output, "\t\tObj.MessageData.Set(Value);"); writeln!(output, "\t\treturn Obj;"); writeln!(output, "\t}}"); writeln!(output); @@ -1444,13 +1555,13 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a output, "\tFORCEINLINE bool IsReducer() const {{ return Tag == ESpacetimeDBEventTag::Reducer; }}" ); - writeln!(output, "\tFORCEINLINE FReducer GetAsReducer() const"); + writeln!(output, "\tFORCEINLINE F{module_prefix}Reducer GetAsReducer() const"); writeln!(output, "\t{{"); writeln!( output, "\t\tensureMsgf(IsReducer(), TEXT(\"MessageData does not hold Reducer!\"));" ); - writeln!(output, "\t\treturn MessageData.Get();"); + writeln!(output, "\t\treturn MessageData.Get();"); writeln!(output, "\t}}"); writeln!(output); writeln!( @@ -1576,7 +1687,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a ); writeln!( output, - " static F{module_name}Event Reducer(const FReducer& InValue)" + " static F{module_name}Event Reducer(const F{module_prefix}Reducer& InValue)" ); writeln!(output, " {{"); writeln!(output, " return F{module_name}Event::Reducer(InValue);"); @@ -1686,7 +1797,7 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a ); writeln!( output, - " static FReducer GetAsReducer(const F{module_name}Event& Event)" + " static F{module_prefix}Reducer GetAsReducer(const F{module_name}Event& Event)" ); writeln!(output, " {{"); writeln!(output, " return Event.GetAsReducer();"); @@ -1764,14 +1875,17 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a // FEventContext, FReducerEventContext, FErrorContext, FSubscriptionEventContext writeln!(output); writeln!(output, "USTRUCT(BlueprintType)"); - writeln!(output, "struct {api_macro} FEventContext : public FContextBase"); + writeln!( + output, + "struct {api_macro} F{module_prefix}EventContext : public F{module_prefix}ContextBase" + ); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); writeln!(output); - writeln!(output, "\tFEventContext() = default;"); + writeln!(output, "\tF{module_prefix}EventContext() = default;"); writeln!( output, - "\tFEventContext(UDbConnection* InConn, const F{module_name}Event& InEvent) : FContextBase(InConn), Event(InEvent) {{}}" + "\tF{module_prefix}EventContext(U{module_prefix}DbConnection* InConn, const F{module_name}Event& InEvent) : F{module_prefix}ContextBase(InConn), Event(InEvent) {{}}" ); writeln!(output); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); @@ -1779,26 +1893,32 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "}};"); writeln!(output); writeln!(output, "USTRUCT(BlueprintType)"); - writeln!(output, "struct {api_macro} FReducerEventContext : public FContextBase"); + writeln!( + output, + "struct {api_macro} F{module_prefix}ReducerEventContext : public F{module_prefix}ContextBase" + ); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); writeln!(output); - writeln!(output, "\tFReducerEventContext() = default;"); - writeln!(output, "\tFReducerEventContext(UDbConnection* InConn, F{module_name}ReducerEvent InEvent) : FContextBase(InConn), Event(InEvent) {{}}"); + writeln!(output, "\tF{module_prefix}ReducerEventContext() = default;"); + writeln!(output, "\tF{module_prefix}ReducerEventContext(U{module_prefix}DbConnection* InConn, F{module_name}ReducerEvent InEvent) : F{module_prefix}ContextBase(InConn), Event(InEvent) {{}}"); writeln!(output, "\t"); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\") "); writeln!(output, "\tF{module_name}ReducerEvent Event;"); writeln!(output, "}};"); writeln!(output); writeln!(output, "USTRUCT(BlueprintType)"); - writeln!(output, "struct {api_macro} FErrorContext : public FContextBase"); + writeln!( + output, + "struct {api_macro} F{module_prefix}ErrorContext : public F{module_prefix}ContextBase" + ); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); writeln!(output); - writeln!(output, "\tFErrorContext() = default;"); + writeln!(output, "\tF{module_prefix}ErrorContext() = default;"); writeln!( output, - "\tFErrorContext(UDbConnection* InConn, const FString& InError) : FContextBase(InConn), Error(InError) {{}}" + "\tF{module_prefix}ErrorContext(U{module_prefix}DbConnection* InConn, const FString& InError) : F{module_prefix}ContextBase(InConn), Error(InError) {{}}" ); writeln!(output); writeln!(output, "\tUPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); @@ -1809,33 +1929,41 @@ fn generate_context_structs(output: &mut UnrealCppAutogen, module: &ModuleDef, a writeln!(output, "USTRUCT(BlueprintType)"); writeln!( output, - "struct {api_macro} FSubscriptionEventContext : public FContextBase" + "struct {api_macro} F{module_prefix}SubscriptionEventContext : public F{module_prefix}ContextBase" ); writeln!(output, "{{"); writeln!(output, "\tGENERATED_BODY()"); writeln!(output); - writeln!(output, "\tFSubscriptionEventContext() = default;"); + writeln!(output, "\tF{module_prefix}SubscriptionEventContext() = default;"); writeln!( output, - "\tFSubscriptionEventContext(UDbConnection* InConn) : FContextBase(InConn) {{}}" + "\tF{module_prefix}SubscriptionEventContext(U{module_prefix}DbConnection* InConn) : F{module_prefix}ContextBase(InConn) {{}}" ); writeln!(output); writeln!(output, "}};"); writeln!(output); writeln!(output, "DECLARE_DYNAMIC_DELEGATE_OneParam("); - writeln!(output, "\tFOnSubscriptionApplied,"); - writeln!(output, "\tFSubscriptionEventContext, Context);"); + writeln!(output, "\tF{module_prefix}OnSubscriptionApplied,"); + writeln!(output, "\tF{module_prefix}SubscriptionEventContext, Context);"); writeln!(output); writeln!(output, "DECLARE_DYNAMIC_DELEGATE_OneParam("); - writeln!(output, "\tFOnSubscriptionError,"); - writeln!(output, "\tFErrorContext, Context);"); + writeln!(output, "\tF{module_prefix}OnSubscriptionError,"); + writeln!(output, "\tF{module_prefix}ErrorContext, Context);"); writeln!(output); } -fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDef, api_macro: &str) { +fn generate_remote_tables_class( + output: &mut UnrealCppAutogen, + module_prefix: &str, + module: &ModuleDef, + api_macro: &str, +) { writeln!(output, "// RemoteTables class"); writeln!(output, "UCLASS(BlueprintType)"); - writeln!(output, "class {api_macro} URemoteTables : public UObject"); + writeln!( + output, + "class {api_macro} U{module_prefix}RemoteTables : public UObject" + ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output); @@ -1845,7 +1973,7 @@ fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDe // Generate table handle properties for table in module.tables() { - let table_pascal = type_ref_name(module, table.product_type_ref); + let table_pascal = type_ref_name(module_prefix, module, table.product_type_ref); writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); writeln!( @@ -1862,13 +1990,17 @@ fn generate_remote_tables_class(output: &mut UnrealCppAutogen, module: &ModuleDe fn generate_remote_reducers_class( output: &mut UnrealCppAutogen, + module_prefix: &str, module: &ModuleDef, api_macro: &str, module_name: &str, ) { writeln!(output, "// RemoteReducers class"); writeln!(output, "UCLASS(BlueprintType)"); - writeln!(output, "class {api_macro} URemoteReducers : public UObject"); + writeln!( + output, + "class {api_macro} U{module_prefix}RemoteReducers : public UObject" + ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output); @@ -1877,7 +2009,8 @@ fn generate_remote_reducers_class( // Generate reducer events and call methods for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{reducer_name}"); // Generate delegate for reducer event let param_count = reducer.params_for_generate.elements.len() + 1; // +1 for context @@ -1890,7 +2023,7 @@ fn generate_remote_reducers_class( // For more than 9 params, use a struct to wrap the arguments writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams("); writeln!(output, " F{reducer_pascal}Handler,"); - writeln!(output, " const FReducerEventContext&, Context,"); + writeln!(output, " const F{module_prefix}ReducerEventContext&, Context,"); writeln!(output, " const F{reducer_pascal}Args&, Args"); writeln!(output, " );"); @@ -1902,7 +2035,7 @@ fn generate_remote_reducers_class( // But functions still need to check individual parameters for (_, param_type) in &reducer.params_for_generate.elements { if !is_type_blueprintable_for_delegates(module, param_type) { - let type_str = cpp_ty_fmt_with_module(module, param_type, module_name).to_string(); + let type_str = cpp_ty_fmt_with_module(module_prefix, module, param_type, module_name).to_string(); non_blueprintable_types_for_function.push(type_str); } } @@ -1923,12 +2056,13 @@ fn generate_remote_reducers_class( write!( output, - " {delegate_macro}(\n F{reducer_pascal}Handler,\n const FReducerEventContext&, Context" + " {delegate_macro}(\n F{reducer_pascal}Handler,\n const F{module_prefix}ReducerEventContext&, Context" ); for (param_name, param_type) in &reducer.params_for_generate.elements { // Use Blueprint-compatible types for delegates - let type_str = cpp_ty_fmt_blueprint_compatible(module, param_type, module_name).to_string(); + let type_str = + cpp_ty_fmt_blueprint_compatible(module_prefix, module, param_type, module_name).to_string(); // Collect non-blueprintable types for both delegate and function if !is_type_blueprintable_for_delegates(module, param_type) { @@ -1966,21 +2100,21 @@ fn generate_remote_reducers_class( " // NOTE: Not exposed to Blueprint because {types_str} types are not Blueprint-compatible" ); } - writeln!(output, " F{reducer_pascal}Handler On{reducer_pascal};"); + writeln!(output, " F{reducer_pascal}Handler On{reducer_name};"); writeln!(output); // Generate call method if non_blueprintable_types_for_function.is_empty() { write!( output, - " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\")\n void {reducer_pascal}(" + " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\")\n void {reducer_name}(" ); } else { // Generate specific message about which types are not Blueprint-compatible let types_str = non_blueprintable_types_for_function.join(", "); write!( output, - " // NOTE: Not exposed to Blueprint because {types_str} types are not Blueprint-compatible\n void {reducer_pascal}(" + " // NOTE: Not exposed to Blueprint because {types_str} types are not Blueprint-compatible\n void {reducer_name}(" ); } @@ -1993,9 +2127,9 @@ fn generate_remote_reducers_class( // For UFUNCTION parameters, use Blueprint-compatible types let type_str = if non_blueprintable_types_for_function.is_empty() { - cpp_ty_fmt_blueprint_compatible(module, param_type, module_name).to_string() + cpp_ty_fmt_blueprint_compatible(module_prefix, module, param_type, module_name).to_string() } else { - cpp_ty_fmt_with_module(module, param_type, module_name).to_string() + cpp_ty_fmt_with_module(module_prefix, module, param_type, module_name).to_string() }; if should_pass_by_value_in_delegate(module, param_type) { @@ -2022,7 +2156,7 @@ fn generate_remote_reducers_class( // Generate invoke method write!( output, - " bool Invoke{reducer_pascal}(const FReducerEventContext& Context, const U{reducer_pascal}Reducer* Args);" + " bool Invoke{reducer_name}(const F{module_prefix}ReducerEventContext& Context, const U{reducer_pascal}Reducer* Args);" ); writeln!(output); writeln!(output); @@ -2030,7 +2164,7 @@ fn generate_remote_reducers_class( // Internal error handling writeln!(output, " // Internal error handling"); - writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error);"); + writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FInternalOnUnhandledReducerError, const F{module_prefix}ReducerEventContext&, Context, const FString&, Error);"); writeln!( output, " FInternalOnUnhandledReducerError InternalOnUnhandledReducerError;" @@ -2039,23 +2173,23 @@ fn generate_remote_reducers_class( writeln!(output, "private:"); writeln!(output); - writeln!(output, " friend UDbConnection;"); + writeln!(output, " friend U{module_prefix}DbConnection;"); writeln!(output); writeln!(output, " UPROPERTY()"); - writeln!(output, " class UDbConnection* Conn;"); + writeln!(output, " class U{module_prefix}DbConnection* Conn;"); writeln!(output); writeln!(output, " UPROPERTY()"); - writeln!(output, " USetReducerFlags* SetCallReducerFlags;"); + writeln!(output, " U{module_prefix}SetReducerFlags* SetCallReducerFlags;"); writeln!(output, "}};"); writeln!(output); } -fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, api_macro: &str) { +fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, module_prefix: &str, api_macro: &str) { writeln!(output, "// SubscriptionBuilder class"); writeln!(output, "UCLASS(BlueprintType)"); writeln!( output, - "class {api_macro} USubscriptionBuilder : public USubscriptionBuilderBase" + "class {api_macro} U{module_prefix}SubscriptionBuilder : public USubscriptionBuilderBase" ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); @@ -2065,19 +2199,19 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, api_macro: writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " USubscriptionBuilder* OnApplied(FOnSubscriptionApplied Callback);" + " U{module_prefix}SubscriptionBuilder* OnApplied(F{module_prefix}OnSubscriptionApplied Callback);" ); writeln!(output); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " USubscriptionBuilder* OnError(FOnSubscriptionError Callback);" + " U{module_prefix}SubscriptionBuilder* OnError(F{module_prefix}OnSubscriptionError Callback);" ); writeln!(output); writeln!(output, " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\")"); writeln!( output, - " USubscriptionHandle* Subscribe(const TArray& SQL);" + " U{module_prefix}SubscriptionHandle* Subscribe(const TArray& SQL);" ); writeln!(output); writeln!( @@ -2085,54 +2219,60 @@ fn generate_subscription_builder_class(output: &mut UnrealCppAutogen, api_macro: " /** Convenience for subscribing to all rows from all tables */" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); - writeln!(output, " USubscriptionHandle* SubscribeToAllTables();"); + writeln!( + output, + " U{module_prefix}SubscriptionHandle* SubscribeToAllTables();" + ); writeln!(output); writeln!(output); - writeln!(output, " friend class UDbConnection;"); + writeln!(output, " friend class U{module_prefix}DbConnection;"); writeln!(output, " friend class UDbConnectionBase;"); writeln!(output); writeln!(output, "protected:"); writeln!(output, " UPROPERTY()"); - writeln!(output, " class UDbConnection* Conn;"); + writeln!(output, " class U{module_prefix}DbConnection* Conn;"); writeln!(output); writeln!( output, " // Delegates stored so Subscribe() can bind forwarding callbacks" ); - writeln!(output, " FOnSubscriptionApplied OnAppliedDelegateInternal;"); - writeln!(output, " FOnSubscriptionError OnErrorDelegateInternal;"); + writeln!(output, " F{module_prefix}OnSubscriptionApplied OnAppliedDelegateInternal;"); + writeln!(output, " F{module_prefix}OnSubscriptionError OnErrorDelegateInternal;"); writeln!(output, "}};"); writeln!(output); } -fn generate_subscription_handle_class(output: &mut UnrealCppAutogen, api_macro: &str) { +fn generate_subscription_handle_class(output: &mut UnrealCppAutogen, module_prefix: &str, api_macro: &str) { writeln!(output, "// SubscriptionHandle class"); writeln!(output, "UCLASS(BlueprintType)"); writeln!( output, - "class {api_macro} USubscriptionHandle : public USubscriptionHandleBase" + "class {api_macro} U{module_prefix}SubscriptionHandle : public USubscriptionHandleBase" ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output); writeln!(output, "public:"); writeln!(output); - writeln!(output, " USubscriptionHandle() {{}};"); + writeln!(output, " U{module_prefix}SubscriptionHandle() {{}};"); writeln!(output); - writeln!(output, " explicit USubscriptionHandle(UDbConnection* InConn);"); + writeln!( + output, + " explicit U{module_prefix}SubscriptionHandle(U{module_prefix}DbConnection* InConn);" + ); writeln!(output); - writeln!(output, " friend class USubscriptionBuilder;"); + writeln!(output, " friend class U{module_prefix}SubscriptionBuilder;"); writeln!(output); writeln!(output, "private:"); writeln!(output, " UPROPERTY()"); - writeln!(output, " class UDbConnection* Conn;"); + writeln!(output, " class U{module_prefix}DbConnection* Conn;"); writeln!(output); writeln!( output, " // Delegates that expose subscription events with connection aware contexts" ); - writeln!(output, " FOnSubscriptionApplied OnAppliedDelegate;"); - writeln!(output, " FOnSubscriptionError OnErrorDelegate;"); + writeln!(output, " F{module_prefix}OnSubscriptionApplied OnAppliedDelegate;"); + writeln!(output, " F{module_prefix}OnSubscriptionError OnErrorDelegate;"); writeln!(output); writeln!(output, " UFUNCTION()"); writeln!( @@ -2146,50 +2286,56 @@ fn generate_subscription_handle_class(output: &mut UnrealCppAutogen, api_macro: writeln!(output); } -fn generate_db_connection_builder_class(output: &mut UnrealCppAutogen, api_macro: &str) { +fn generate_db_connection_builder_class(output: &mut UnrealCppAutogen, module_prefix: &str, api_macro: &str) { writeln!(output, "/*"); writeln!(output, " @Note: Child class of UDbConnectionBuilderBase."); writeln!(output, "*/"); writeln!(output, "UCLASS(BlueprintType)"); writeln!( output, - "class {api_macro} UDbConnectionBuilder : public UDbConnectionBuilderBase" + "class {api_macro} U{module_prefix}DbConnectionBuilder : public UDbConnectionBuilderBase" ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output, "public:"); writeln!(output); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); - writeln!(output, " UDbConnectionBuilder* WithUri(const FString& InUri);"); + writeln!( + output, + " U{module_prefix}DbConnectionBuilder* WithUri(const FString& InUri);" + ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " UDbConnectionBuilder* WithModuleName(const FString& InName);" + " U{module_prefix}DbConnectionBuilder* WithModuleName(const FString& InName);" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); - writeln!(output, " UDbConnectionBuilder* WithToken(const FString& InToken);"); + writeln!( + output, + " U{module_prefix}DbConnectionBuilder* WithToken(const FString& InToken);" + ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " UDbConnectionBuilder* WithCompression(const ESpacetimeDBCompression& InCompression);" + " U{module_prefix}DbConnectionBuilder* WithCompression(const ESpacetimeDBCompression& InCompression);" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " UDbConnectionBuilder* OnConnect(FOnConnectDelegate Callback);" + " U{module_prefix}DbConnectionBuilder* OnConnect(F{module_prefix}OnConnectDelegate Callback);" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " UDbConnectionBuilder* OnConnectError(FOnConnectErrorDelegate Callback);" + " U{module_prefix}DbConnectionBuilder* OnConnectError(FOnConnectErrorDelegate Callback);" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); writeln!( output, - " UDbConnectionBuilder* OnDisconnect(FOnDisconnectDelegate Callback);" + " U{module_prefix}DbConnectionBuilder* OnDisconnect(F{module_prefix}OnDisconnectDelegate Callback);" ); writeln!(output, " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\")"); - writeln!(output, " UDbConnection* Build();"); + writeln!(output, " U{module_prefix}DbConnection* Build();"); writeln!(output); writeln!(output, "private:"); writeln!(output); @@ -2197,58 +2343,72 @@ fn generate_db_connection_builder_class(output: &mut UnrealCppAutogen, api_macro output, " // Stored delegates which will be forwarded when the connection events occur." ); - writeln!(output, " FOnConnectDelegate OnConnectDelegateInternal;"); - writeln!(output, " FOnDisconnectDelegate OnDisconnectDelegateInternal;"); + writeln!(output, " F{module_prefix}OnConnectDelegate OnConnectDelegateInternal;"); + writeln!(output, " F{module_prefix}OnDisconnectDelegate OnDisconnectDelegateInternal;"); writeln!(output, "}};"); writeln!(output); } -fn generate_db_connection_class(output: &mut UnrealCppAutogen, _module: &ModuleDef, api_macro: &str) { +fn generate_db_connection_class( + output: &mut UnrealCppAutogen, + module_prefix: &str, + _module: &ModuleDef, + api_macro: &str, + module_name: &str, +) { writeln!(output, "// Main DbConnection class"); writeln!(output, "UCLASS(BlueprintType)"); - writeln!(output, "class {api_macro} UDbConnection : public UDbConnectionBase"); + writeln!( + output, + "class {api_macro} U{module_prefix}DbConnection : public UDbConnectionBase" + ); writeln!(output, "{{"); writeln!(output, " GENERATED_BODY()"); writeln!(output); writeln!(output, "public:"); writeln!( output, - " explicit UDbConnection(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());" + " explicit U{module_prefix}DbConnection(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());" ); writeln!(output); writeln!(output); writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); - writeln!(output, " URemoteTables* Db;"); + writeln!(output, " U{module_prefix}RemoteTables* Db;"); writeln!(output); writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); - writeln!(output, " URemoteReducers* Reducers;"); + writeln!(output, " U{module_prefix}RemoteReducers* Reducers;"); writeln!(output); writeln!(output, " UPROPERTY(BlueprintReadOnly, Category=\"SpacetimeDB\")"); - writeln!(output, " USetReducerFlags* SetReducerFlags;"); + writeln!(output, " U{module_prefix}SetReducerFlags* SetReducerFlags;"); writeln!(output); writeln!( output, " // Delegates that allow users to bind with the concrete connection type." ); - writeln!(output, " FOnConnectDelegate OnConnectDelegate;"); - writeln!(output, " FOnDisconnectDelegate OnDisconnectDelegate;"); + writeln!(output, " F{module_prefix}OnConnectDelegate OnConnectDelegate;"); + writeln!(output, " F{module_prefix}OnDisconnectDelegate OnDisconnectDelegate;"); writeln!(output); writeln!(output, " UFUNCTION(BlueprintCallable, Category=\"SpacetimeDB\")"); - writeln!(output, " USubscriptionBuilder* SubscriptionBuilder();"); + writeln!( + output, + " U{module_prefix}SubscriptionBuilder* SubscriptionBuilder();" + ); writeln!(output); writeln!(output, " /** Static entry point for constructing a connection. */"); writeln!( output, - " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\", DisplayName = \"SpacetimeDB Builder\")" + " UFUNCTION(BlueprintCallable, Category = \"SpacetimeDB\", DisplayName = \"SpacetimeDB {module_name} Builder\")" ); - writeln!(output, " static UDbConnectionBuilder* Builder();"); + writeln!(output, " static U{module_prefix}DbConnectionBuilder* Builder();"); writeln!(output); writeln!(output, " // Error handling"); - writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledReducerError, const FReducerEventContext&, Context, const FString&, Error);"); + writeln!(output, " DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnUnhandledReducerError, const F{module_prefix}ReducerEventContext&, Context, const FString&, Error);"); writeln!(output, " UPROPERTY(BlueprintAssignable, Category=\"SpacetimeDB\")"); writeln!(output, " FOnUnhandledReducerError OnUnhandledReducerError;"); writeln!(output); writeln!(output); + writeln!(output, " friend U{module_prefix}SubscriptionBuilder;"); + writeln!(output, " friend U{module_prefix}DbConnectionBuilder;"); writeln!(output, "protected:"); writeln!(output); writeln!(output, " // Hook up error handling to reducers"); @@ -2265,7 +2425,7 @@ fn generate_db_connection_class(output: &mut UnrealCppAutogen, _module: &ModuleD writeln!(output, " UFUNCTION()"); writeln!( output, - " void OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error);" + " void OnUnhandledReducerErrorHandler(const F{module_prefix}ReducerEventContext& Context, const FString& Error);" ); writeln!(output); writeln!( @@ -2295,9 +2455,17 @@ fn generate_db_connection_class(output: &mut UnrealCppAutogen, _module: &ModuleD writeln!(output); } -fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &ModuleDef, module_name: &str) { +fn generate_client_implementation( + output: &mut UnrealCppAutogen, + module_prefix: &str, + module: &ModuleDef, + module_name: &str, +) { // Helper: Decode reducer args into FReducer from either event types - writeln!(output, "static FReducer DecodeReducer(const FReducerEvent& Event)"); + writeln!( + output, + "static F{module_prefix}Reducer DecodeReducer(const FReducerEvent& Event)" + ); writeln!(output, "{{"); writeln!( output, @@ -2306,51 +2474,52 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); for reducer in iter_reducers(module) { - let reducer_name = reducer.name.deref(); - let reducer_pascal = reducer_name.to_case(Case::Pascal); + let reducer_original = reducer.name.deref(); + let reducer_name = reducer_original.to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{}", reducer_name); - writeln!(output, " if (ReducerName == TEXT(\"{reducer_name}\"))"); + writeln!(output, " if (ReducerName == TEXT(\"{reducer_original}\"))"); writeln!(output, " {{"); writeln!( output, " F{reducer_pascal}Args Args = UE::SpacetimeDB::Deserialize(Event.ReducerCall.Args);" ); - writeln!(output, " return FReducer::{reducer_pascal}(Args);"); + writeln!(output, " return F{module_prefix}Reducer::{reducer_name}(Args);"); writeln!(output, " }}"); writeln!(output); } - writeln!(output, " return FReducer();"); + writeln!(output, " return F{module_prefix}Reducer();"); writeln!(output, "}}"); writeln!(output); // UDbConnection constructor writeln!( output, - "UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)" + "U{module_prefix}DbConnection::U{module_prefix}DbConnection(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)" ); writeln!(output, "{{"); - writeln!(output, "\tSetReducerFlags = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"SetReducerFlags\"));"); + writeln!(output, "\tSetReducerFlags = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"SetReducerFlags\"));"); writeln!(output); writeln!( output, - "\tDb = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"RemoteTables\"));" + "\tDb = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"RemoteTables\"));" ); writeln!(output, "\tDb->Initialize();"); writeln!(output, "\t"); writeln!( output, - "\tReducers = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"RemoteReducers\"));" + "\tReducers = ObjectInitializer.CreateDefaultSubobject(this, TEXT(\"RemoteReducers\"));" ); writeln!(output, "\tReducers->SetCallReducerFlags = SetReducerFlags;"); writeln!(output, "\tReducers->Conn = this;"); writeln!(output); for table in module.tables() { - let table_pascal = type_ref_name(module, table.product_type_ref); + let table_pascal = type_ref_name(module_prefix, module, table.product_type_ref); let table_name = table.name.deref(); writeln!( output, - "\tRegisterTable(TEXT(\"{}\"), Db->{});", + "\tRegisterTable(TEXT(\"{}\"), Db->{});", table_pascal, table_pascal, table_name, @@ -2361,7 +2530,10 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); // FContextBase constructor - writeln!(output, "FContextBase::FContextBase(UDbConnection* InConn)"); + writeln!( + output, + "F{module_prefix}ContextBase::F{module_prefix}ContextBase(U{module_prefix}DbConnection* InConn)" + ); writeln!(output, "{{"); writeln!(output, "\tDb = InConn->Db;"); writeln!(output, "\tReducers = InConn->Reducers;"); @@ -2370,38 +2542,44 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); // FContextBase methods - writeln!(output, "bool FContextBase::IsActive() const"); + writeln!(output, "bool F{module_prefix}ContextBase::IsActive() const"); writeln!(output, "{{"); writeln!(output, "\treturn Conn->IsActive();"); writeln!(output, "}}"); - writeln!(output, "void FContextBase::Disconnect()"); + writeln!(output, "void F{module_prefix}ContextBase::Disconnect()"); writeln!(output, "{{"); writeln!(output, "\tConn->Disconnect();"); writeln!(output, "}}"); - writeln!(output, "USubscriptionBuilder* FContextBase::SubscriptionBuilder()"); + writeln!( + output, + "U{module_prefix}SubscriptionBuilder* F{module_prefix}ContextBase::SubscriptionBuilder()" + ); writeln!(output, "{{"); writeln!(output, "\treturn Conn->SubscriptionBuilder();"); writeln!(output, "}}"); writeln!( output, - "bool FContextBase::TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const" + "bool F{module_prefix}ContextBase::TryGetIdentity(FSpacetimeDBIdentity& OutIdentity) const" ); writeln!(output, "{{"); writeln!(output, "\treturn Conn->TryGetIdentity(OutIdentity);"); writeln!(output, "}}"); - writeln!(output, "FSpacetimeDBConnectionId FContextBase::GetConnectionId() const"); + writeln!( + output, + "FSpacetimeDBConnectionId F{module_prefix}ContextBase::GetConnectionId() const" + ); writeln!(output, "{{"); writeln!(output, "\treturn Conn->GetConnectionId();"); writeln!(output, "}}"); writeln!(output); // URemoteTables Initialize method - writeln!(output, "void URemoteTables::Initialize()"); + writeln!(output, "void U{module_prefix}RemoteTables::Initialize()"); writeln!(output, "{{"); writeln!(output); writeln!(output, "\t/** Creating tables */"); for table in module.tables() { - let table_pascal = type_ref_name(module, table.product_type_ref); + let table_pascal = type_ref_name(module_prefix, module, table.product_type_ref); writeln!( output, "\t{} = NewObject(this);", @@ -2425,24 +2603,26 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module // USetReducerFlags methods for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + writeln!( output, - "void USetReducerFlags::{reducer_pascal}(ECallReducerFlags Flag)" + "void U{module_prefix}SetReducerFlags::{reducer_name}(ECallReducerFlags Flag)" ); writeln!(output, "{{"); - writeln!(output, "\tFlagMap.Add(\"{reducer_pascal}\", Flag);"); + writeln!(output, "\tFlagMap.Add(\"{reducer_name}\", Flag);"); writeln!(output, "}}"); } writeln!(output); // Reducer implementations for reducer in iter_reducers(module) { - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); - let reducer_snake = reducer.name.deref(); + let reducer_original = reducer.name.deref(); + let reducer_name = reducer_original.to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{reducer_name}"); // Call method implementation - write!(output, "void URemoteReducers::{reducer_pascal}("); + write!(output, "void U{module_prefix}RemoteReducers::{reducer_name}("); let mut first = true; for (param_name, param_type) in &reducer.params_for_generate.elements { if !first { @@ -2450,7 +2630,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module } first = false; // Use Blueprint-compatible types (same as UFUNCTION and delegates) - let type_str = cpp_ty_fmt_blueprint_compatible(module, param_type, module_name).to_string(); + let type_str = cpp_ty_fmt_blueprint_compatible(module_prefix, module, param_type, module_name).to_string(); if should_pass_by_value_in_delegate(module, param_type) { // Primitives use const by-value in URemoteReducers methods (same as UFUNCTION) write!( @@ -2484,12 +2664,12 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module if reducer.params_for_generate.elements.is_empty() { writeln!( output, - "\tConn->CallReducerTyped(TEXT(\"{reducer_snake}\"), F{reducer_pascal}Args(), SetCallReducerFlags);" + "\tConn->CallReducerTyped(TEXT(\"{reducer_original}\"), F{reducer_pascal}Args(), SetCallReducerFlags);" ); } else { write!( output, - "\tConn->CallReducerTyped(TEXT(\"{reducer_snake}\"), F{reducer_pascal}Args(" + "\tConn->CallReducerTyped(TEXT(\"{reducer_original}\"), F{reducer_pascal}Args(" ); let mut first = true; for (param_name, _) in &reducer.params_for_generate.elements { @@ -2508,11 +2688,11 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module // Invoke method implementation write!( output, - "bool URemoteReducers::Invoke{reducer_pascal}(const FReducerEventContext& Context, const U{reducer_pascal}Reducer* Args)" + "bool U{module_prefix}RemoteReducers::Invoke{reducer_name}(const F{module_prefix}ReducerEventContext& Context, const U{reducer_pascal}Reducer* Args)" ); writeln!(output); writeln!(output, "{{"); - writeln!(output, " if (!On{reducer_pascal}.IsBound())"); + writeln!(output, " if (!On{reducer_name}.IsBound())"); writeln!(output, " {{"); writeln!(output, " // Handle unhandled reducer error"); writeln!(output, " if (InternalOnUnhandledReducerError.IsBound())"); @@ -2524,7 +2704,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, " // For now, just broadcast any error"); writeln!( output, - " InternalOnUnhandledReducerError.Broadcast(Context, TEXT(\"No handler registered for {reducer_pascal}\"));" + " InternalOnUnhandledReducerError.Broadcast(Context, TEXT(\"No handler registered for {reducer_name}\"));" ); writeln!(output, " }}"); writeln!(output, " return false;"); @@ -2542,10 +2722,10 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module let param_pascal = param_name.deref().to_case(Case::Pascal); writeln!(output, " ArgsStruct.{param_pascal} = Args->{param_pascal};"); } - writeln!(output, " On{reducer_pascal}.Broadcast(Context, ArgsStruct);"); + writeln!(output, " On{reducer_name}.Broadcast(Context, ArgsStruct);"); } else { // Use individual parameters - write!(output, " On{reducer_pascal}.Broadcast(Context"); + write!(output, " On{reducer_name}.Broadcast(Context"); for (param_name, _) in &reducer.params_for_generate.elements { let param_pascal = param_name.deref().to_case(Case::Pascal); write!(output, ", Args->{param_pascal}"); @@ -2559,7 +2739,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module } // Hook up error handling - writeln!(output, "void UDbConnection::PostInitProperties()"); + writeln!(output, "void U{module_prefix}DbConnection::PostInitProperties()"); writeln!(output, "{{"); writeln!(output, " Super::PostInitProperties();"); writeln!(output, " "); @@ -2569,7 +2749,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module ); writeln!(output, " if (Reducers)"); writeln!(output, " {{"); - writeln!(output, " Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &UDbConnection::OnUnhandledReducerErrorHandler);"); + writeln!(output, " Reducers->InternalOnUnhandledReducerError.AddDynamic(this, &U{module_prefix}DbConnection::OnUnhandledReducerErrorHandler);"); writeln!(output, " }}"); writeln!(output, "}}"); writeln!(output); @@ -2578,7 +2758,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "UFUNCTION()"); writeln!( output, - "void UDbConnection::OnUnhandledReducerErrorHandler(const FReducerEventContext& Context, const FString& Error)" + "void U{module_prefix}DbConnection::OnUnhandledReducerErrorHandler(const F{module_prefix}ReducerEventContext& Context, const FString& Error)" ); writeln!(output, "{{"); writeln!(output, " if (OnUnhandledReducerError.IsBound())"); @@ -2589,13 +2769,19 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); // ReducerEvent method implementation - writeln!(output, "void UDbConnection::ReducerEvent(const FReducerEvent& Event)"); + writeln!( + output, + "void U{module_prefix}DbConnection::ReducerEvent(const FReducerEvent& Event)" + ); writeln!(output, "{{"); writeln!(output, " if (!Reducers) {{ return; }}"); writeln!(output); // Decode reducer call args - writeln!(output, " FReducer DecodedReducer = DecodeReducer(Event);"); + writeln!( + output, + " F{module_prefix}Reducer DecodedReducer = DecodeReducer(Event);" + ); writeln!(output); let module_name_pascal = module_name.to_case(Case::Pascal); @@ -2612,7 +2798,10 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, " ReducerEvent.Reducer = DecodedReducer;"); writeln!(output); - writeln!(output, " FReducerEventContext Context(this, ReducerEvent);"); + writeln!( + output, + " F{module_prefix}ReducerEventContext Context(this, ReducerEvent);" + ); writeln!(output); writeln!(output, " // Use hardcoded string matching for reducer dispatching"); writeln!( @@ -2622,13 +2811,14 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); for reducer in iter_reducers(module) { - let reducer_name = reducer.name.deref(); - let reducer_pascal = reducer.name.deref().to_case(Case::Pascal); - writeln!(output, " if (ReducerName == TEXT(\"{reducer_name}\"))"); + let reducer_original = reducer.name.deref(); + let reducer_name = reducer.name.deref().to_case(Case::Pascal); + let reducer_pascal = format!("{module_prefix}{}", reducer.name.deref().to_case(Case::Pascal)); + writeln!(output, " if (ReducerName == TEXT(\"{reducer_original}\"))"); writeln!(output, " {{"); writeln!( output, - " F{reducer_pascal}Args Args = ReducerEvent.Reducer.GetAs{reducer_pascal}();" + " F{reducer_pascal}Args Args = ReducerEvent.Reducer.GetAs{reducer_name}();" ); writeln!( output, @@ -2641,7 +2831,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, " Reducer->{param_pascal} = Args.{param_pascal};"); } - writeln!(output, " Reducers->Invoke{reducer_pascal}(Context, Reducer);"); + writeln!(output, " Reducers->Invoke{reducer_name}(Context, Reducer);"); writeln!(output, " return;"); writeln!(output, " }}"); } @@ -2656,7 +2846,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module // ReducerEventFailed method implementation writeln!( output, - "void UDbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage)" + "void U{module_prefix}DbConnection::ReducerEventFailed(const FReducerEvent& Event, const FString ErrorMessage)" ); writeln!(output, "{{"); writeln!(output, " if (!Reducers) {{ return; }}"); @@ -2674,7 +2864,10 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, " ReducerEvent.Timestamp = Event.Timestamp;"); writeln!(output); - writeln!(output, " FReducerEventContext Context(this, ReducerEvent);"); + writeln!( + output, + " F{module_prefix}ReducerEventContext Context(this, ReducerEvent);" + ); writeln!(output); writeln!(output, " if (Reducers->InternalOnUnhandledReducerError.IsBound())"); writeln!(output, " {{"); @@ -2687,23 +2880,29 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); // Additional methods from manual reference - writeln!(output, "UDbConnectionBuilder* UDbConnection::Builder()"); + writeln!( + output, + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnection::Builder()" + ); writeln!(output, "{{"); - writeln!(output, "\treturn NewObject();"); + writeln!(output, "\treturn NewObject();"); writeln!(output, "}}"); writeln!(output, "// Added for creating subscriptions"); - writeln!(output, "USubscriptionBuilder* UDbConnection::SubscriptionBuilder()"); + writeln!( + output, + "U{module_prefix}SubscriptionBuilder* U{module_prefix}DbConnection::SubscriptionBuilder()" + ); writeln!(output, "{{"); writeln!( output, - "\tUSubscriptionBuilder* Builder = NewObject(this);" + "\tU{module_prefix}SubscriptionBuilder* Builder = NewObject(this);" ); writeln!(output, "\tBuilder->Conn = this;"); writeln!(output, "\treturn Builder;"); writeln!(output, "}}"); writeln!( output, - "USubscriptionBuilder* USubscriptionBuilder::OnApplied(FOnSubscriptionApplied Callback)" + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnApplied(F{module_prefix}OnSubscriptionApplied Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnAppliedDelegateInternal = Callback;"); @@ -2711,7 +2910,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); writeln!( output, - "USubscriptionBuilder* USubscriptionBuilder::OnError(FOnSubscriptionError Callback)" + "U{module_prefix}SubscriptionBuilder* U{module_prefix}SubscriptionBuilder::OnError(F{module_prefix}OnSubscriptionError Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnErrorDelegateInternal = Callback;"); @@ -2719,12 +2918,12 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); writeln!( output, - "USubscriptionHandle* USubscriptionBuilder::Subscribe(const TArray& SQL)" + "U{module_prefix}SubscriptionHandle* U{module_prefix}SubscriptionBuilder::Subscribe(const TArray& SQL)" ); writeln!(output, "{{"); writeln!( output, - "\tUSubscriptionHandle* Handle = NewObject();" + "\tU{module_prefix}SubscriptionHandle* Handle = NewObject();" ); writeln!(output); writeln!(output, "\t// Store user callbacks on the handle"); @@ -2753,7 +2952,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); writeln!( output, - "USubscriptionHandle* USubscriptionBuilder::SubscribeToAllTables()" + "U{module_prefix}SubscriptionHandle* U{module_prefix}SubscriptionBuilder::SubscribeToAllTables()" ); writeln!(output, "{{"); writeln!(output, "\treturn Subscribe({{ \"SELECT * FROM * \" }});"); @@ -2761,7 +2960,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); writeln!( output, - "USubscriptionHandle::USubscriptionHandle(UDbConnection* InConn)" + "U{module_prefix}SubscriptionHandle::U{module_prefix}SubscriptionHandle(U{module_prefix}DbConnection* InConn)" ); writeln!(output, "{{"); writeln!(output, "\tConn = InConn;"); @@ -2769,24 +2968,24 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); writeln!( output, - "void USubscriptionHandle::ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx)" + "void U{module_prefix}SubscriptionHandle::ForwardOnApplied(const FSubscriptionEventContextBase& BaseCtx)" ); writeln!(output, "{{"); writeln!(output, "\tif (OnAppliedDelegate.IsBound())"); writeln!(output, "\t{{"); - writeln!(output, "\t\tFSubscriptionEventContext Ctx(Conn);"); + writeln!(output, "\t\tF{module_prefix}SubscriptionEventContext Ctx(Conn);"); writeln!(output, "\t\tOnAppliedDelegate.Execute(Ctx);"); writeln!(output, "\t}}"); writeln!(output, "}}"); writeln!(output); writeln!( output, - "void USubscriptionHandle::ForwardOnError(const FErrorContextBase& BaseCtx)" + "void U{module_prefix}SubscriptionHandle::ForwardOnError(const FErrorContextBase& BaseCtx)" ); writeln!(output, "{{"); writeln!(output, "\tif (OnErrorDelegate.IsBound())"); writeln!(output, "\t{{"); - writeln!(output, "\t\tFErrorContext Ctx(Conn, BaseCtx.Error);"); + writeln!(output, "\t\tF{module_prefix}ErrorContext Ctx(Conn, BaseCtx.Error);"); writeln!(output, "\t\tOnErrorDelegate.Execute(Ctx);"); writeln!(output, "\t}}"); writeln!(output, "}}"); @@ -2795,41 +2994,47 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "// Cast from parent to child class"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::WithUri(const FString& InUri)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::WithUri(const FString& InUri)" ); writeln!(output, "{{"); - writeln!(output, "\treturn Cast(WithUriBase(InUri));"); + writeln!( + output, + "\treturn Cast(WithUriBase(InUri));" + ); writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::WithModuleName(const FString& InName)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::WithModuleName(const FString& InName)" ); writeln!(output, "{{"); writeln!( output, - "\treturn Cast(WithModuleNameBase(InName));" + "\treturn Cast(WithModuleNameBase(InName));" ); writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::WithToken(const FString& InToken)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::WithToken(const FString& InToken)" ); writeln!(output, "{{"); - writeln!(output, "\treturn Cast(WithTokenBase(InToken));"); + writeln!( + output, + "\treturn Cast(WithTokenBase(InToken));" + ); writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::WithCompression(const ESpacetimeDBCompression& InCompression)" ); writeln!(output, "{{"); writeln!( output, - "\treturn Cast(WithCompressionBase(InCompression));" + "\treturn Cast(WithCompressionBase(InCompression));" ); writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::OnConnect(FOnConnectDelegate Callback)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::OnConnect(F{module_prefix}OnConnectDelegate Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnConnectDelegateInternal = Callback;"); @@ -2837,25 +3042,31 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::OnConnectError(FOnConnectErrorDelegate Callback)" ); writeln!(output, "{{"); writeln!( output, - "\treturn Cast(OnConnectErrorBase(Callback));" + "\treturn Cast(OnConnectErrorBase(Callback));" ); writeln!(output, "}}"); writeln!( output, - "UDbConnectionBuilder* UDbConnectionBuilder::OnDisconnect(FOnDisconnectDelegate Callback)" + "U{module_prefix}DbConnectionBuilder* U{module_prefix}DbConnectionBuilder::OnDisconnect(F{module_prefix}OnDisconnectDelegate Callback)" ); writeln!(output, "{{"); writeln!(output, "\tOnDisconnectDelegateInternal = Callback;"); writeln!(output, "\treturn this;"); writeln!(output, "}}"); - writeln!(output, "UDbConnection* UDbConnectionBuilder::Build()"); + writeln!( + output, + "U{module_prefix}DbConnection* U{module_prefix}DbConnectionBuilder::Build()" + ); writeln!(output, "{{"); - writeln!(output, "\tUDbConnection* Connection = NewObject();"); + writeln!( + output, + "\tU{module_prefix}DbConnection* Connection = NewObject();" + ); writeln!(output); writeln!(output, "\t// Store delegates on the connection for later use"); writeln!(output, "\tConnection->OnConnectDelegate = OnConnectDelegateInternal;"); @@ -2881,9 +3092,12 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "\tConnection->SetOnDisconnectDelegate(BaseDisconnect);"); writeln!(output, "\tOnDisconnectBase(BaseDisconnect);"); writeln!(output); - writeln!(output, "\treturn Cast(BuildConnection(Connection));"); + writeln!( + output, + "\treturn Cast(BuildConnection(Connection));" + ); writeln!(output, "}}"); - writeln!(output, "void UDbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken)"); + writeln!(output, "void U{module_prefix}DbConnection::ForwardOnConnect(UDbConnectionBase* BaseConnection, FSpacetimeDBIdentity InIdentity, const FString& InToken)"); writeln!(output, "{{"); writeln!(output, "\tif (OnConnectDelegate.IsBound())"); writeln!(output, "\t{{"); @@ -2892,7 +3106,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, "}}"); writeln!( output, - "void UDbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error)" + "void U{module_prefix}DbConnection::ForwardOnDisconnect(UDbConnectionBase* BaseConnection, const FString& Error)" ); writeln!(output, "{{"); writeln!(output, "\tif (OnDisconnectDelegate.IsBound())"); @@ -2905,7 +3119,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!( output, - "void UDbConnection::DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event)" + "void U{module_prefix}DbConnection::DbUpdate(const FDatabaseUpdateType& Update, const FSpacetimeDBEvent& Event)" ); writeln!(output, "{{"); @@ -2922,7 +3136,10 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output, " case ESpacetimeDBEventTag::Reducer:"); writeln!(output, " {{"); writeln!(output, " FReducerEvent ReducerEvent = Event.GetAsReducer();"); - writeln!(output, " FReducer Reducer = DecodeReducer(ReducerEvent);"); + writeln!( + output, + " F{module_prefix}Reducer Reducer = DecodeReducer(ReducerEvent);" + ); writeln!( output, " BaseEvent = F{module_name_pascal}Event::Reducer(Reducer);" @@ -2978,7 +3195,7 @@ fn generate_client_implementation(output: &mut UnrealCppAutogen, module: &Module writeln!(output); // Wrap in EventContext - writeln!(output, " FEventContext Context(this, BaseEvent);"); + writeln!(output, " F{module_prefix}EventContext Context(this, BaseEvent);"); writeln!( output, " // Populate typed reducer args for convenience in table handlers" @@ -3046,33 +3263,33 @@ impl UnrealCppAutogen { // Helpers // --------------------------------------------------------------------------- -fn collect_optional_types(module: &ModuleDef) -> HashSet { +fn collect_optional_types(module_prefix: &str, module: &ModuleDef) -> HashSet { let mut optional_types = HashSet::new(); // Helper function to collect from a type - fn collect_from_type(module: &ModuleDef, ty: &AlgebraicTypeUse, out: &mut HashSet) { + fn collect_from_type(module_prefix: &str, module: &ModuleDef, ty: &AlgebraicTypeUse, out: &mut HashSet) { match ty { AlgebraicTypeUse::Option(inner) => { // Generate the optional type name - let optional_name = get_optional_type_name(module, inner); + let optional_name = get_optional_type_name(module_prefix, module, inner); out.insert(optional_name); // Recursively collect from inner type - collect_from_type(module, inner, out); + collect_from_type(module_prefix, module, inner, out); } AlgebraicTypeUse::Array(elem) => { - collect_from_type(module, elem, out); + collect_from_type(module_prefix, module, elem, out); } AlgebraicTypeUse::Ref(r) => { // Check if the referenced type contains optionals match &module.typespace_for_generate()[*r] { AlgebraicTypeDef::Product(product) => { for (_, field_ty) in &product.elements { - collect_from_type(module, field_ty, out); + collect_from_type(module_prefix, module, field_ty, out); } } AlgebraicTypeDef::Sum(sum) => { for (_, variant_ty) in &sum.variants { - collect_from_type(module, variant_ty, out); + collect_from_type(module_prefix, module, variant_ty, out); } } _ => {} @@ -3088,7 +3305,7 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { .as_product() .unwrap(); for (_, field_ty) in &product_type.elements { - collect_from_type(module, field_ty, &mut optional_types); + collect_from_type(module_prefix, module, field_ty, &mut optional_types); } } @@ -3097,12 +3314,12 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { match &module.typespace_for_generate()[typ.ty] { AlgebraicTypeDef::Product(product) => { for (_, field_ty) in &product.elements { - collect_from_type(module, field_ty, &mut optional_types); + collect_from_type(module_prefix, module, field_ty, &mut optional_types); } } AlgebraicTypeDef::Sum(sum) => { for (_, variant_ty) in &sum.variants { - collect_from_type(module, variant_ty, &mut optional_types); + collect_from_type(module_prefix, module, variant_ty, &mut optional_types); } } _ => {} @@ -3112,7 +3329,7 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { // Collect from reducer parameters for reducer in iter_reducers(module) { for (_, param_ty) in &reducer.params_for_generate.elements { - collect_from_type(module, param_ty, &mut optional_types); + collect_from_type(module_prefix, module, param_ty, &mut optional_types); } } @@ -3120,7 +3337,13 @@ fn collect_optional_types(module: &ModuleDef) -> HashSet { } // Helper function to get C++ type for array elements in optional arrays -fn get_cpp_type_for_array_element(elem_type_str: &str, _: &ModuleDef, module_name: &str) -> String { +fn get_cpp_type_for_array_element( + module_prefix: &str, + module: &ModuleDef, + elem_type_str: &str, + _: &ModuleDef, + module_name: &str, +) -> String { match elem_type_str { "Bool" => "bool".to_string(), "I8" | "Int8" => "int8".to_string(), @@ -3149,13 +3372,32 @@ fn get_cpp_type_for_array_element(elem_type_str: &str, _: &ModuleDef, module_nam format!("F{module_name_pascal}OptionalInt32") } _ => { - format!("E{elem_type_str}Type") + let is_enum = module.types().any(|type_def| { + let type_name = type_def + .name + .name_segments() + .last() + .map(|id| id.deref().to_string()) + .unwrap_or_else(|| "Unnamed".to_string()); + let prefixed_type_name = format!("{module_prefix}{type_name}"); + prefixed_type_name == elem_type_str + && matches!( + module.typespace_for_generate()[type_def.ty], + AlgebraicTypeDef::PlainEnum(_) + ) + }); + + if is_enum { + format!("E{elem_type_str}Type") + } else { + format!("F{elem_type_str}Type") + } } } } // Helper function to get array element type name for optional array types -fn get_array_element_type_name(module: &ModuleDef, elem: &AlgebraicTypeUse) -> String { +fn get_array_element_type_name(module_prefix: &str, module: &ModuleDef, elem: &AlgebraicTypeUse) -> String { match elem { AlgebraicTypeUse::Primitive(p) => match p { PrimitiveType::Bool => "Bool".to_string(), @@ -3180,17 +3422,17 @@ fn get_array_element_type_name(module: &ModuleDef, elem: &AlgebraicTypeUse) -> S AlgebraicTypeUse::Timestamp => "Timestamp".to_string(), AlgebraicTypeUse::TimeDuration => "TimeDuration".to_string(), AlgebraicTypeUse::ScheduleAt => "ScheduleAt".to_string(), - AlgebraicTypeUse::Ref(r) => type_ref_name(module, *r), + AlgebraicTypeUse::Ref(r) => type_ref_name(module_prefix, module, *r), AlgebraicTypeUse::Option(nested_inner) => { // Handle optional elements in arrays like Vec> - get_optional_type_name(module, nested_inner) + get_optional_type_name(module_prefix, module, nested_inner) } _ => "Unknown".to_string(), } } // Get the name for an optional type (e.g., "OptionalString", "OptionalInt32") -fn get_optional_type_name(module: &ModuleDef, inner: &AlgebraicTypeUse) -> String { +fn get_optional_type_name(module_prefix: &str, module: &ModuleDef, inner: &AlgebraicTypeUse) -> String { match inner { AlgebraicTypeUse::Primitive(p) => match p { PrimitiveType::Bool => "OptionalBool".to_string(), @@ -3217,24 +3459,68 @@ fn get_optional_type_name(module: &ModuleDef, inner: &AlgebraicTypeUse) -> Strin AlgebraicTypeUse::ScheduleAt => "OptionalScheduleAt".to_string(), AlgebraicTypeUse::Array(elem) => { // Generate specific optional array types based on element type - let elem_name = get_array_element_type_name(module, elem); + let elem_name = get_array_element_type_name(module_prefix, module, elem); format!("OptionalVec{elem_name}") } AlgebraicTypeUse::Ref(r) => { - let type_name = type_ref_name(module, *r); + let type_name = type_ref_name(module_prefix, module, *r); format!("Optional{type_name}") } AlgebraicTypeUse::Option(nested_inner) => { // Handle nested optionals like Option> - let inner_optional_name = get_optional_type_name(module, nested_inner); + let inner_optional_name = get_optional_type_name(module_prefix, module, nested_inner); format!("Optional{inner_optional_name}") } _ => "OptionalUnknown".to_string(), } } +fn get_extra_includes_for_type(extra_includes: &mut HashSet, inner_type_str: &str) { + match inner_type_str { + "Identity" | "ConnectionId" | "Timestamp" | "TimeDuration" | "ScheduleAt" => { + extra_includes.insert("Types/Builtins.h".to_string()); + } + "Int128" | "UInt128" | "Int256" | "UInt256" => { + extra_includes.insert("Types/LargeIntegers.h".to_string()); + } + "String" | "Bool" | "Int8" | "UInt8" | "Int16" | "UInt16" | "Int32" | "UInt32" | "Int64" | "UInt64" + | "Float" | "Double" | "Array" => { + // Basic types, no extra includes needed + } + _ if !inner_type_str.starts_with("Int") && !inner_type_str.starts_with("UInt") => { + // Custom type, need its header + extra_includes.insert(format!("ModuleBindings/Types/{inner_type_str}Type.g.h")); + } + _ => { + extra_includes.insert(format!("ModuleBindings/Types/{inner_type_str}.g.h")); + } + } +} + +fn optional_ty_init_fmt_impl(cpp_inner_type: &str) -> String { + match cpp_inner_type { + "bool" => " = false".to_string(), + "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "float" | "double" => { + " = 0".to_string() + } + _ => { + if cpp_inner_type.starts_with("E") { + format!(" = static_cast<{}>(0)", cpp_inner_type) + } else { + "".to_string() + } + } + } +} + // Generate the content for an optional type file -fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &str, module_name: &str) -> String { +fn generate_optional_type( + optional_name: &str, + module_prefix: &str, + module: &ModuleDef, + api_macro: &str, + module_name: &str, +) -> String { // Extract the inner type from the optional name let inner_type_str = optional_name.strip_prefix("Optional").unwrap_or(optional_name); @@ -3276,7 +3562,8 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s _ if inner_type_str.starts_with("Vec") => { // Handle OptionalVecXxx -> should use TArray let elem_type_str = &inner_type_str[3..]; // Remove "Vec" prefix - let cpp_elem_type = get_cpp_type_for_array_element(elem_type_str, module, module_name); + let cpp_elem_type = + get_cpp_type_for_array_element(module_prefix, module, elem_type_str, module, module_name); format!("TArray<{cpp_elem_type}>") } _ => { @@ -3288,7 +3575,8 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s .last() .map(|id| id.deref().to_string()) .unwrap_or_else(|| "Unnamed".to_string()); - type_name == inner_type_str + let prefixed_type_name = format!("{module_prefix}{type_name}"); + prefixed_type_name == inner_type_str && matches!( module.typespace_for_generate()[type_def.ty], AlgebraicTypeDef::PlainEnum(_) @@ -3304,34 +3592,49 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s }; // Determine if we need extra includes - let mut extra_includes = vec![]; + let mut extra_includes = HashSet::new(); match inner_type_str { "Identity" | "ConnectionId" | "Timestamp" | "TimeDuration" | "ScheduleAt" => { - extra_includes.push("Types/Builtins.h".to_string()); + extra_includes.insert("Types/Builtins.h".to_string()); } "Int128" | "UInt128" | "Int256" | "UInt256" => { - extra_includes.push("Types/LargeIntegers.h".to_string()); + extra_includes.insert("Types/LargeIntegers.h".to_string()); } "String" | "Bool" | "Int8" | "UInt8" | "Int16" | "UInt16" | "Int32" | "UInt32" | "Int64" | "UInt64" | "Float" | "Double" | "Array" => { // Basic types, no extra includes needed } + _ if inner_type_str.starts_with("VecOptional") => { + let elem_type_str = &inner_type_str[11..]; // Remove "VecOptional" prefix + let module_name_pascal = module_name.to_case(Case::Pascal); + extra_includes.insert(format!( + "ModuleBindings/Optionals/{module_name_pascal}Optional{elem_type_str}.g.h" + )); + } _ if inner_type_str.starts_with("Vec") => { - // Not required + let elem_type_str = &inner_type_str[3..]; // Remove "Vec" prefix + get_extra_includes_for_type(&mut extra_includes, elem_type_str); + } + _ if inner_type_str.starts_with("OptionalVecOptional") => { + let module_name_pascal = module_name.to_case(Case::Pascal); + extra_includes.insert(format!( + "ModuleBindings/Optionals/{module_name_pascal}{inner_type_str}.g.h" + )); } _ if inner_type_str.starts_with("OptionalVec") => { - // Not required + let elem_type_str = &inner_type_str[11..]; // Remove "OptionalVec" prefix + get_extra_includes_for_type(&mut extra_includes, elem_type_str); } _ if inner_type_str.starts_with("Optional") => { // Nested optional, need its header let module_name_pascal = module_name.to_case(Case::Pascal); - extra_includes.push(format!( + extra_includes.insert(format!( "ModuleBindings/Optionals/{module_name_pascal}{inner_type_str}.g.h" )); } _ if !inner_type_str.starts_with("Int") && !inner_type_str.starts_with("UInt") => { // Custom type, need its header - extra_includes.push(format!("ModuleBindings/Types/{inner_type_str}Type.g.h")); + extra_includes.insert(format!("ModuleBindings/Types/{inner_type_str}Type.g.h")); } _ => {} } @@ -3388,7 +3691,8 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s "// NOTE: {cpp_inner_type} field not exposed to Blueprint due to non-blueprintable elements" ); } - writeln!(output, "{cpp_inner_type} Value;"); + let init_str = optional_ty_init_fmt_impl(cpp_inner_type.as_str()); + writeln!(output, "{cpp_inner_type} Value{init_str};"); writeln!(output); // Constructors @@ -3461,6 +3765,7 @@ fn generate_optional_type(optional_name: &str, module: &ModuleDef, api_macro: &s } fn autogen_cpp_struct( + module_prefix: &str, module: &ModuleDef, name: &str, // Changed to &str product_type: &ProductTypeDef, @@ -3470,7 +3775,7 @@ fn autogen_cpp_struct( let mut headers = HashSet::::new(); for (_, field_ty) in product_type { - collect_includes_for_type(module, field_ty, &mut headers, module_name); + collect_includes_for_type(module_prefix, module, field_ty, &mut headers, module_name); } // Convert to `Vec<&str>` so UnrealCppAutogen::new works @@ -3490,10 +3795,9 @@ fn autogen_cpp_struct( for (orig_name, ty) in product_type.into_iter() { let field_name = orig_name.deref().to_case(Case::Pascal); - let ty_str = cpp_ty_fmt_with_module(module, ty, module_name).to_string(); - let init_str = cpp_ty_init_fmt_impl(ty); + let ty_str = cpp_ty_fmt_with_module(module_prefix, module, ty, module_name).to_string(); + let init_str = cpp_ty_init_fmt_impl(ty, ty_str.as_str()); let field_decl = format!("{ty_str} {field_name}{init_str}"); - // Check if the type is blueprintable if is_blueprintable(module, ty) { writeln!( @@ -3760,6 +4064,7 @@ fn autogen_cpp_enum(name: &str, enum_type: &PlainEnumTypeDef) -> String { } fn autogen_cpp_sum( + module_prefix: &str, module: &ModuleDef, name: &str, sum_type: &SumTypeDef, @@ -3773,7 +4078,7 @@ fn autogen_cpp_sum( /* ------------------------------------------------------------------ */ let mut includes = HashSet::::new(); for (_, alg_ty) in &sum_type.variants { - collect_includes_for_type(module, alg_ty, &mut includes, module_name); + collect_includes_for_type(module_prefix, module, alg_ty, &mut includes, module_name); } includes.insert("Kismet/BlueprintFunctionLibrary.h".to_string()); @@ -3797,7 +4102,7 @@ fn autogen_cpp_sum( let comma = if ix + 1 == sum_type.variants.len() { "" } else { "," }; writeln!(output, " {}{}", variant.to_case(Case::Pascal), comma); - let variant_cpp_type = cpp_ty_fmt_with_module(module, _variant_type, module_name).to_string(); + let variant_cpp_type = cpp_ty_fmt_with_module(module_prefix, module, _variant_type, module_name).to_string(); variant_type.insert(variant_cpp_type); } writeln!(output, "}};\n"); @@ -3833,7 +4138,7 @@ fn autogen_cpp_sum( /* 4a. Static factories per variant -------------------------------- */ for (variant_name, variant_type) in &sum_type.variants { let pas = variant_name.to_case(Case::Pascal); - let variant_cpp_type = cpp_ty_fmt_with_module(module, variant_type, module_name).to_string(); + let variant_cpp_type = cpp_ty_fmt_with_module(module_prefix, module, variant_type, module_name).to_string(); let param_type = format!("const {variant_cpp_type}& "); writeln!(output, " static F{name}Type {pas}({param_type}Value)\n {{"); @@ -3850,7 +4155,7 @@ fn autogen_cpp_sum( /* 4b. Get/Is helpers ---------------------------------------------- */ for (variant_name, variant_type) in &sum_type.variants { let pas = variant_name.to_case(Case::Pascal); - let variant_cpp_type = cpp_ty_fmt_with_module(module, variant_type, module_name).to_string(); + let variant_cpp_type = cpp_ty_fmt_with_module(module_prefix, module, variant_type, module_name).to_string(); // Is* writeln!( @@ -3970,7 +4275,7 @@ fn autogen_cpp_sum( let variant_count = sum_type.variants.len(); for (idx, (variant_name, variant_type)) in sum_type.variants.iter().enumerate() { let variant_pascal = variant_name.to_case(Case::Pascal); - let variant_cpp_type = cpp_ty_fmt_with_module(module, variant_type, module_name).to_string(); + let variant_cpp_type = cpp_ty_fmt_with_module(module_prefix, module, variant_type, module_name).to_string(); if idx < variant_count - 1 { writeln!(output, " {variant_pascal}, {variant_cpp_type},"); @@ -3994,7 +4299,7 @@ fn autogen_cpp_sum( for (variant_name, variant_type) in &sum_type.variants { let pas = variant_name.to_case(Case::Pascal); - let variant_cpp_type = cpp_ty_fmt_with_module(module, variant_type, module_name).to_string(); + let variant_cpp_type = cpp_ty_fmt_with_module(module_prefix, module, variant_type, module_name).to_string(); // ctor functions if is_blueprintable(module, variant_type) { @@ -4067,40 +4372,44 @@ impl IdentifierCasing for Identifier { } fn cpp_ty_fmt_with_module<'a>( + module_prefix: &'a str, module: &'a ModuleDef, ty: &'a AlgebraicTypeUse, module_name: &'a str, ) -> impl fmt::Display + 'a { - cpp_ty_fmt_impl(module, ty, module_name) + cpp_ty_fmt_impl(module_prefix, module, ty, module_name) } fn cpp_ty_fmt_blueprint_compatible<'a>( + module_prefix: &'a str, module: &'a ModuleDef, ty: &'a AlgebraicTypeUse, module_name: &'a str, ) -> impl fmt::Display + 'a { - cpp_ty_fmt_blueprint_impl(module, ty, module_name) + cpp_ty_fmt_blueprint_impl(module_prefix, module, ty, module_name) } fn cpp_ty_fmt_blueprint_impl<'a>( + module_prefix: &'a str, module: &'a ModuleDef, ty: &'a AlgebraicTypeUse, module_name: &'a str, ) -> impl fmt::Display + 'a { fmt_fn(move |f| match ty { AlgebraicTypeUse::Array(elem) => { - let elem_type = cpp_ty_fmt_with_module(module, elem, module_name).to_string(); + let elem_type = cpp_ty_fmt_with_module(module_prefix, module, elem, module_name).to_string(); write!(f, "TArray<{elem_type}>") } // For all other types, use the regular implementation _ => { - let display_obj = cpp_ty_fmt_with_module(module, ty, module_name); + let display_obj = cpp_ty_fmt_with_module(module_prefix, module, ty, module_name); write!(f, "{display_obj}") } }) } fn cpp_ty_fmt_impl<'a>( + module_prefix: &'a str, module: &'a ModuleDef, ty: &'a AlgebraicTypeUse, module_name: &'a str, @@ -4130,7 +4439,7 @@ fn cpp_ty_fmt_impl<'a>( } AlgebraicTypeUse::Array(elem) => { - let elem_type = cpp_ty_fmt_impl(module, elem, module_name).to_string(); + let elem_type = cpp_ty_fmt_impl(module_prefix, module, elem, module_name).to_string(); write!(f, "TArray<{elem_type}>") } @@ -4144,7 +4453,7 @@ fn cpp_ty_fmt_impl<'a>( // --------- references to user-defined types --------- AlgebraicTypeUse::Ref(r) => { - let scoped = type_ref_name(module, *r); // PascalCase + let scoped = type_ref_name(module_prefix, module, *r); // PascalCase match &module.typespace_for_generate()[*r] { AlgebraicTypeDef::PlainEnum(_) => write!(f, "E{scoped}Type"), // enum → EFooType AlgebraicTypeDef::Product(_) => write!(f, "F{scoped}Type"), // struct/record → FFooType @@ -4154,7 +4463,7 @@ fn cpp_ty_fmt_impl<'a>( // Options use the generated optional types AlgebraicTypeUse::Option(inner) => { - let optional_name = get_optional_type_name(module, inner); + let optional_name = get_optional_type_name(module_prefix, module, inner); if module_name.is_empty() { write!(f, "F{optional_name}") } else { @@ -4169,7 +4478,7 @@ fn cpp_ty_fmt_impl<'a>( // For UPROPERTY() Unreal expects initialization values for certain types // (e.g. bools default to true if not explicitly initialized to false). -fn cpp_ty_init_fmt_impl<'a>(ty: &'a AlgebraicTypeUse) -> impl fmt::Display + 'a { +fn cpp_ty_init_fmt_impl<'a>(ty: &'a AlgebraicTypeUse, type_name: &'a str) -> impl fmt::Display + 'a { fmt_fn(move |f| match ty { AlgebraicTypeUse::Primitive(p) => f.write_str(match p { PrimitiveType::Bool => " = false", @@ -4197,7 +4506,15 @@ fn cpp_ty_init_fmt_impl<'a>(ty: &'a AlgebraicTypeUse) -> impl fmt::Display + 'a AlgebraicTypeUse::ScheduleAt => f.write_str(""), AlgebraicTypeUse::Unit => f.write_str(""), // --------- references to user-defined types --------- - AlgebraicTypeUse::Ref(_r) => f.write_str(""), + AlgebraicTypeUse::Ref(_r) => { + if type_name.starts_with("E") { + f.write_str(" = static_cast<") + .and_then(|_| f.write_str(type_name)) + .and_then(|_| f.write_str(">(0)")) + } else { + f.write_str("") + } + } // Options use the generated optional types AlgebraicTypeUse::Option(_inner) => f.write_str(""), AlgebraicTypeUse::Never => unreachable!("never type"), @@ -4207,6 +4524,7 @@ fn cpp_ty_init_fmt_impl<'a>(ty: &'a AlgebraicTypeUse) -> impl fmt::Display + 'a // Given an `AlgebraicTypeUse`, add every referenced type’s generated // header name (`".g.h"`) into `out` (a `HashSet` avoids dups). fn collect_includes_for_type( + module_prefix: &str, module: &ModuleDef, ty: &AlgebraicTypeUse, out: &mut std::collections::HashSet, @@ -4215,20 +4533,23 @@ fn collect_includes_for_type( use AlgebraicTypeUse::*; match ty { Ref(r) => { - let header = format!("ModuleBindings/Types/{}Type.g.h", type_ref_name(module, *r)); + let header = format!( + "ModuleBindings/Types/{}Type.g.h", + type_ref_name(module_prefix, module, *r) + ); out.insert(header); } Option(inner) => { // Add the optional type header - let optional_name = get_optional_type_name(module, inner); + let optional_name = get_optional_type_name(module_prefix, module, inner); let module_name_pascal = module_name.to_case(Case::Pascal); let header = format!("ModuleBindings/Optionals/{module_name_pascal}{optional_name}.g.h"); out.insert(header); // Also collect includes for the inner type - collect_includes_for_type(module, inner, out, module_name); + collect_includes_for_type(module_prefix, module, inner, out, module_name); } Array(inner) => { - collect_includes_for_type(module, inner, out, module_name); + collect_includes_for_type(module_prefix, module, inner, out, module_name); } // Builtin types that require Builtins.h (also includes LargeIntegers.h) Identity | ConnectionId | Timestamp | TimeDuration | ScheduleAt => { @@ -4259,11 +4580,127 @@ fn collect_includes_for_type( } // UnrealCPP-specific type reference name function that preserves original case -fn type_ref_name(module: &ModuleDef, typeref: spacetimedb_lib::sats::AlgebraicTypeRef) -> String { +fn type_ref_name(module_prefix: &str, module: &ModuleDef, typeref: spacetimedb_lib::sats::AlgebraicTypeRef) -> String { let (name, _def) = module.type_def_from_ref(typeref).unwrap(); // Preserve original case instead of applying Pascal case conversion - name.name_segments() + let base_name = name + .name_segments() .last() .map(|id| id.deref().to_string()) - .unwrap_or_else(|| "Unnamed".to_string()) + .unwrap_or_else(|| "Unnamed".to_string()); + + format!("{module_prefix}{base_name}") +} + +fn ensure_module_in_uproject(uproject_dir: &Path, module_name: &str) -> Result<(), String> { + // Find .uproject file + let uproject_file = std::fs::read_dir(uproject_dir) + .map_err(|e| format!("Cannot read uproject directory: {}", e))? + .filter_map(|entry| entry.ok()) + .find(|entry| { + entry + .path() + .extension() + .and_then(|ext| ext.to_str()) + .map(|ext| ext == "uproject") + .unwrap_or(false) + }) + .ok_or("No .uproject file found")?; + + let uproject_path = uproject_file.path(); + + // Read and parse JSON + let content = std::fs::read_to_string(&uproject_path).map_err(|e| format!("Cannot read .uproject file: {}", e))?; + + let mut json: serde_json::Value = + serde_json::from_str(&content).map_err(|e| format!("Invalid JSON in .uproject file: {}", e))?; + + // Ensure Modules array exists + if !json.is_object() { + json = serde_json::json!({}); + } + + let json_obj = json.as_object_mut().unwrap(); + + if !json_obj.contains_key("Modules") { + json_obj.insert("Modules".to_string(), serde_json::Value::Array(vec![])); + } + + let modules = json_obj + .get_mut("Modules") + .and_then(|m| m.as_array_mut()) + .ok_or("Modules is not an array in .uproject file")?; + + // Check if module already exists + let module_exists = modules.iter().any(|module| { + module + .get("Name") + .and_then(|name| name.as_str()) + .map(|name| name == module_name) + .unwrap_or(false) + }); + + // Add module if it doesn't exist + if !module_exists { + let new_module = serde_json::json!({ + "Name": module_name, + "Type": "Runtime", + "LoadingPhase": "Default" + }); + modules.push(new_module); + + // Write back to file with proper formatting + let formatted_json = + serde_json::to_string_pretty(&json).map_err(|e| format!("Failed to serialize JSON: {}", e))?; + + std::fs::write(&uproject_path, formatted_json).map_err(|e| format!("Failed to write .uproject file: {}", e))?; + } + + Ok(()) +} + +fn generate_build_cs_content(module_name: &str) -> String { + format!( + r#"using UnrealBuildTool; + +public class {module_name} : ModuleRules +{{ + public {module_name}(ReadOnlyTargetRules Target) : base(Target) + {{ + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] {{ + "Core", + "CoreUObject", + "Engine", + "SpacetimeDbSdk" + }}); + + PrivateDependencyModuleNames.AddRange(new string[] {{ + // Add private dependencies here + }}); + }} +}} +"#, + module_name = module_name + ) +} + +fn generate_module_cpp_content(module_name: &str) -> String { + format!( + r#"#include "{module_name}.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {module_name}, "{module_name}"); +"#, + module_name = module_name + ) +} + +fn generate_module_h_content(_module_name: &str) -> String { + r#"#pragma once + +#include "CoreMinimal.h" +"# + .to_string() } diff --git a/docs/docs/05-CLI Reference/01-cli-reference.md b/docs/docs/05-CLI Reference/01-cli-reference.md index 558e9436c2c..b5117d1d619 100644 --- a/docs/docs/05-CLI Reference/01-cli-reference.md +++ b/docs/docs/05-CLI Reference/01-cli-reference.md @@ -251,7 +251,7 @@ Run `spacetime rename --help` for more detailed information. Generate client files for a spacetime module. -**Usage:** `spacetime spacetime generate --lang --out-dir [--project-path | --bin-path | --module-name | --uproject-dir ]` +**Usage:** `spacetime spacetime generate --lang --out-dir [--project-path | --bin-path | --module-name | --uproject-dir | --module-prefix ]` Run `spacetime help publish` for more detailed information. @@ -269,6 +269,7 @@ Run `spacetime help publish` for more detailed information. Default value: `SpacetimeDB.Types` - `--module-name ` — The module name that should be used for DLL export macros (required for lang unrealcpp) +- `--module-prefix ` — The module prefix to use for generated types (only used with --lang unrealcpp) - `-l`, `--lang ` — The language to generate Possible values: `csharp`, `typescript`, `rust`, `unrealcpp` diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp index 96501d29030..4f9c24f2f47 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Private/ModuleBindings/SpacetimeDBClient.g.cpp @@ -4,104 +4,104 @@ #include "ModuleBindings/SpacetimeDBClient.g.h" #include "DBCache/WithBsatn.h" #include "BSATN/UEBSATNHelpers.h" -#include "ModuleBindings/Tables/IndexedSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/OneU128Table.g.h" -#include "ModuleBindings/Tables/UniqueI8Table.g.h" -#include "ModuleBindings/Tables/UniqueU16Table.g.h" -#include "ModuleBindings/Tables/BTreeU32Table.g.h" -#include "ModuleBindings/Tables/IndexedTableTable.g.h" -#include "ModuleBindings/Tables/OptionEveryPrimitiveStructTable.g.h" -#include "ModuleBindings/Tables/UniqueI256Table.g.h" -#include "ModuleBindings/Tables/OptionVecOptionI32Table.g.h" #include "ModuleBindings/Tables/UniqueU128Table.g.h" -#include "ModuleBindings/Tables/VecI128Table.g.h" -#include "ModuleBindings/Tables/OneByteStructTable.g.h" -#include "ModuleBindings/Tables/VecI32Table.g.h" -#include "ModuleBindings/Tables/PkU32Table.g.h" -#include "ModuleBindings/Tables/PkStringTable.g.h" -#include "ModuleBindings/Tables/PkU128Table.g.h" -#include "ModuleBindings/Tables/VecU64Table.g.h" -#include "ModuleBindings/Tables/IndexedTable2Table.g.h" +#include "ModuleBindings/Tables/OneU64Table.g.h" +#include "ModuleBindings/Tables/PkI8Table.g.h" #include "ModuleBindings/Tables/VecF64Table.g.h" -#include "ModuleBindings/Tables/OneU256Table.g.h" -#include "ModuleBindings/Tables/OneEveryPrimitiveStructTable.g.h" +#include "ModuleBindings/Tables/UniqueBoolTable.g.h" #include "ModuleBindings/Tables/UniqueI128Table.g.h" -#include "ModuleBindings/Tables/VecI64Table.g.h" -#include "ModuleBindings/Tables/PkU8Table.g.h" -#include "ModuleBindings/Tables/OneF64Table.g.h" -#include "ModuleBindings/Tables/VecU32Table.g.h" +#include "ModuleBindings/Tables/OptionStringTable.g.h" #include "ModuleBindings/Tables/PkI16Table.g.h" -#include "ModuleBindings/Tables/PkI32Table.g.h" -#include "ModuleBindings/Tables/OneU32Table.g.h" -#include "ModuleBindings/Tables/UniqueBoolTable.g.h" -#include "ModuleBindings/Tables/OneSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/VecI16Table.g.h" -#include "ModuleBindings/Tables/UniqueIdentityTable.g.h" -#include "ModuleBindings/Tables/PkU32TwoTable.g.h" -#include "ModuleBindings/Tables/VecBoolTable.g.h" -#include "ModuleBindings/Tables/OneEnumWithPayloadTable.g.h" -#include "ModuleBindings/Tables/UniqueI32Table.g.h" -#include "ModuleBindings/Tables/OneIdentityTable.g.h" +#include "ModuleBindings/Tables/UniqueU8Table.g.h" +#include "ModuleBindings/Tables/VecEveryPrimitiveStructTable.g.h" #include "ModuleBindings/Tables/OneUnitStructTable.g.h" -#include "ModuleBindings/Tables/UsersTable.g.h" -#include "ModuleBindings/Tables/VecConnectionIdTable.g.h" -#include "ModuleBindings/Tables/PkI128Table.g.h" -#include "ModuleBindings/Tables/PkSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/PkI64Table.g.h" -#include "ModuleBindings/Tables/OneI128Table.g.h" +#include "ModuleBindings/Tables/PkStringTable.g.h" +#include "ModuleBindings/Tables/UniqueI32Table.g.h" +#include "ModuleBindings/Tables/UniqueU32Table.g.h" +#include "ModuleBindings/Tables/VecU8Table.g.h" +#include "ModuleBindings/Tables/OneSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/PkU64Table.g.h" +#include "ModuleBindings/Tables/OneEveryVecStructTable.g.h" #include "ModuleBindings/Tables/PkConnectionIdTable.g.h" -#include "ModuleBindings/Tables/OneI16Table.g.h" -#include "ModuleBindings/Tables/LargeTableTable.g.h" +#include "ModuleBindings/Tables/ScheduledTableTable.g.h" +#include "ModuleBindings/Tables/VecI128Table.g.h" +#include "ModuleBindings/Tables/VecU32Table.g.h" +#include "ModuleBindings/Tables/VecUnitStructTable.g.h" +#include "ModuleBindings/Tables/TableHoldsTableTable.g.h" +#include "ModuleBindings/Tables/VecU64Table.g.h" +#include "ModuleBindings/Tables/OneIdentityTable.g.h" +#include "ModuleBindings/Tables/OneI256Table.g.h" +#include "ModuleBindings/Tables/OneU128Table.g.h" +#include "ModuleBindings/Tables/OptionI32Table.g.h" +#include "ModuleBindings/Tables/OneF32Table.g.h" #include "ModuleBindings/Tables/VecEnumWithPayloadTable.g.h" -#include "ModuleBindings/Tables/OneI32Table.g.h" -#include "ModuleBindings/Tables/VecF32Table.g.h" -#include "ModuleBindings/Tables/UniqueConnectionIdTable.g.h" -#include "ModuleBindings/Tables/OptionSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/OneI16Table.g.h" #include "ModuleBindings/Tables/VecI256Table.g.h" -#include "ModuleBindings/Tables/VecTimestampTable.g.h" -#include "ModuleBindings/Tables/PkI8Table.g.h" -#include "ModuleBindings/Tables/OneI256Table.g.h" -#include "ModuleBindings/Tables/ScheduledTableTable.g.h" -#include "ModuleBindings/Tables/UniqueU256Table.g.h" -#include "ModuleBindings/Tables/OneStringTable.g.h" -#include "ModuleBindings/Tables/VecU16Table.g.h" -#include "ModuleBindings/Tables/VecU256Table.g.h" -#include "ModuleBindings/Tables/OptionStringTable.g.h" -#include "ModuleBindings/Tables/OneU16Table.g.h" +#include "ModuleBindings/Tables/UniqueI256Table.g.h" +#include "ModuleBindings/Tables/OneEnumWithPayloadTable.g.h" +#include "ModuleBindings/Tables/PkSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/IndexedTableTable.g.h" +#include "ModuleBindings/Tables/OneByteStructTable.g.h" +#include "ModuleBindings/Tables/OneU256Table.g.h" #include "ModuleBindings/Tables/PkIdentityTable.g.h" -#include "ModuleBindings/Tables/PkU64Table.g.h" -#include "ModuleBindings/Tables/UniqueI16Table.g.h" -#include "ModuleBindings/Tables/VecEveryPrimitiveStructTable.g.h" +#include "ModuleBindings/Tables/UniqueI8Table.g.h" +#include "ModuleBindings/Tables/VecI64Table.g.h" +#include "ModuleBindings/Tables/PkBoolTable.g.h" +#include "ModuleBindings/Tables/PkU32Table.g.h" +#include "ModuleBindings/Tables/OneConnectionIdTable.g.h" +#include "ModuleBindings/Tables/VecStringTable.g.h" +#include "ModuleBindings/Tables/PkU32TwoTable.g.h" +#include "ModuleBindings/Tables/OneBoolTable.g.h" +#include "ModuleBindings/Tables/PkI64Table.g.h" +#include "ModuleBindings/Tables/OneU16Table.g.h" +#include "ModuleBindings/Tables/UniqueStringTable.g.h" +#include "ModuleBindings/Tables/OneTimestampTable.g.h" +#include "ModuleBindings/Tables/OneU8Table.g.h" #include "ModuleBindings/Tables/VecU128Table.g.h" +#include "ModuleBindings/Tables/VecU256Table.g.h" +#include "ModuleBindings/Tables/VecTimestampTable.g.h" #include "ModuleBindings/Tables/OneI8Table.g.h" -#include "ModuleBindings/Tables/UniqueU8Table.g.h" +#include "ModuleBindings/Tables/PkI32Table.g.h" +#include "ModuleBindings/Tables/UniqueI64Table.g.h" +#include "ModuleBindings/Tables/OptionEveryPrimitiveStructTable.g.h" +#include "ModuleBindings/Tables/OneU32Table.g.h" +#include "ModuleBindings/Tables/VecIdentityTable.g.h" #include "ModuleBindings/Tables/VecByteStructTable.g.h" -#include "ModuleBindings/Tables/OneU64Table.g.h" -#include "ModuleBindings/Tables/TableHoldsTableTable.g.h" -#include "ModuleBindings/Tables/UniqueStringTable.g.h" -#include "ModuleBindings/Tables/OneTimestampTable.g.h" -#include "ModuleBindings/Tables/VecSimpleEnumTable.g.h" -#include "ModuleBindings/Tables/OptionI32Table.g.h" -#include "ModuleBindings/Tables/PkBoolTable.g.h" +#include "ModuleBindings/Tables/PkI128Table.g.h" +#include "ModuleBindings/Tables/VecI32Table.g.h" +#include "ModuleBindings/Tables/UniqueConnectionIdTable.g.h" +#include "ModuleBindings/Tables/UniqueI16Table.g.h" +#include "ModuleBindings/Tables/LargeTableTable.g.h" +#include "ModuleBindings/Tables/IndexedSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/OneI128Table.g.h" +#include "ModuleBindings/Tables/OptionVecOptionI32Table.g.h" #include "ModuleBindings/Tables/PkI256Table.g.h" -#include "ModuleBindings/Tables/OneEveryVecStructTable.g.h" -#include "ModuleBindings/Tables/UniqueI64Table.g.h" -#include "ModuleBindings/Tables/UniqueU32Table.g.h" #include "ModuleBindings/Tables/PkU16Table.g.h" -#include "ModuleBindings/Tables/OneConnectionIdTable.g.h" -#include "ModuleBindings/Tables/OneI64Table.g.h" +#include "ModuleBindings/Tables/UniqueIdentityTable.g.h" +#include "ModuleBindings/Tables/UniqueU256Table.g.h" #include "ModuleBindings/Tables/UniqueU64Table.g.h" +#include "ModuleBindings/Tables/OneStringTable.g.h" +#include "ModuleBindings/Tables/VecI8Table.g.h" +#include "ModuleBindings/Tables/VecSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/VecI16Table.g.h" +#include "ModuleBindings/Tables/OptionIdentityTable.g.h" +#include "ModuleBindings/Tables/PkU8Table.g.h" +#include "ModuleBindings/Tables/OneF64Table.g.h" +#include "ModuleBindings/Tables/OneEveryPrimitiveStructTable.g.h" +#include "ModuleBindings/Tables/OptionSimpleEnumTable.g.h" +#include "ModuleBindings/Tables/VecU16Table.g.h" +#include "ModuleBindings/Tables/PkU128Table.g.h" +#include "ModuleBindings/Tables/OneI32Table.g.h" +#include "ModuleBindings/Tables/UsersTable.g.h" +#include "ModuleBindings/Tables/UniqueU16Table.g.h" +#include "ModuleBindings/Tables/IndexedTable2Table.g.h" +#include "ModuleBindings/Tables/VecConnectionIdTable.g.h" +#include "ModuleBindings/Tables/OneI64Table.g.h" +#include "ModuleBindings/Tables/BTreeU32Table.g.h" #include "ModuleBindings/Tables/PkU256Table.g.h" -#include "ModuleBindings/Tables/VecU8Table.g.h" -#include "ModuleBindings/Tables/VecIdentityTable.g.h" -#include "ModuleBindings/Tables/OneU8Table.g.h" +#include "ModuleBindings/Tables/VecBoolTable.g.h" +#include "ModuleBindings/Tables/VecF32Table.g.h" #include "ModuleBindings/Tables/VecEveryVecStructTable.g.h" -#include "ModuleBindings/Tables/VecUnitStructTable.g.h" -#include "ModuleBindings/Tables/OneBoolTable.g.h" -#include "ModuleBindings/Tables/VecStringTable.g.h" -#include "ModuleBindings/Tables/OneF32Table.g.h" -#include "ModuleBindings/Tables/OptionIdentityTable.g.h" -#include "ModuleBindings/Tables/VecI8Table.g.h" static FReducer DecodeReducer(const FReducerEvent& Event) { @@ -1201,104 +1201,104 @@ UDbConnection::UDbConnection(const FObjectInitializer& ObjectInitializer) : Supe Reducers->SetCallReducerFlags = SetReducerFlags; Reducers->Conn = this; - RegisterTable(TEXT("indexed_simple_enum"), Db->IndexedSimpleEnum); - RegisterTable(TEXT("one_u128"), Db->OneU128); - RegisterTable(TEXT("unique_i8"), Db->UniqueI8); - RegisterTable(TEXT("unique_u16"), Db->UniqueU16); - RegisterTable(TEXT("btree_u32"), Db->BtreeU32); - RegisterTable(TEXT("indexed_table"), Db->IndexedTable); - RegisterTable(TEXT("option_every_primitive_struct"), Db->OptionEveryPrimitiveStruct); - RegisterTable(TEXT("unique_i256"), Db->UniqueI256); - RegisterTable(TEXT("option_vec_option_i32"), Db->OptionVecOptionI32); RegisterTable(TEXT("unique_u128"), Db->UniqueU128); - RegisterTable(TEXT("vec_i128"), Db->VecI128); - RegisterTable(TEXT("one_byte_struct"), Db->OneByteStruct); - RegisterTable(TEXT("vec_i32"), Db->VecI32); - RegisterTable(TEXT("pk_u32"), Db->PkU32); - RegisterTable(TEXT("pk_string"), Db->PkString); - RegisterTable(TEXT("pk_u128"), Db->PkU128); - RegisterTable(TEXT("vec_u64"), Db->VecU64); - RegisterTable(TEXT("indexed_table_2"), Db->IndexedTable2); + RegisterTable(TEXT("one_u64"), Db->OneU64); + RegisterTable(TEXT("pk_i8"), Db->PkI8); RegisterTable(TEXT("vec_f64"), Db->VecF64); - RegisterTable(TEXT("one_u256"), Db->OneU256); - RegisterTable(TEXT("one_every_primitive_struct"), Db->OneEveryPrimitiveStruct); + RegisterTable(TEXT("unique_bool"), Db->UniqueBool); RegisterTable(TEXT("unique_i128"), Db->UniqueI128); - RegisterTable(TEXT("vec_i64"), Db->VecI64); - RegisterTable(TEXT("pk_u8"), Db->PkU8); - RegisterTable(TEXT("one_f64"), Db->OneF64); - RegisterTable(TEXT("vec_u32"), Db->VecU32); + RegisterTable(TEXT("option_string"), Db->OptionString); RegisterTable(TEXT("pk_i16"), Db->PkI16); - RegisterTable(TEXT("pk_i32"), Db->PkI32); - RegisterTable(TEXT("one_u32"), Db->OneU32); - RegisterTable(TEXT("unique_bool"), Db->UniqueBool); - RegisterTable(TEXT("one_simple_enum"), Db->OneSimpleEnum); - RegisterTable(TEXT("vec_i16"), Db->VecI16); - RegisterTable(TEXT("unique_identity"), Db->UniqueIdentity); - RegisterTable(TEXT("pk_u32_two"), Db->PkU32Two); - RegisterTable(TEXT("vec_bool"), Db->VecBool); - RegisterTable(TEXT("one_enum_with_payload"), Db->OneEnumWithPayload); - RegisterTable(TEXT("unique_i32"), Db->UniqueI32); - RegisterTable(TEXT("one_identity"), Db->OneIdentity); + RegisterTable(TEXT("unique_u8"), Db->UniqueU8); + RegisterTable(TEXT("vec_every_primitive_struct"), Db->VecEveryPrimitiveStruct); RegisterTable(TEXT("one_unit_struct"), Db->OneUnitStruct); - RegisterTable(TEXT("users"), Db->Users); - RegisterTable(TEXT("vec_connection_id"), Db->VecConnectionId); - RegisterTable(TEXT("pk_i128"), Db->PkI128); - RegisterTable(TEXT("pk_simple_enum"), Db->PkSimpleEnum); - RegisterTable(TEXT("pk_i64"), Db->PkI64); - RegisterTable(TEXT("one_i128"), Db->OneI128); + RegisterTable(TEXT("pk_string"), Db->PkString); + RegisterTable(TEXT("unique_i32"), Db->UniqueI32); + RegisterTable(TEXT("unique_u32"), Db->UniqueU32); + RegisterTable(TEXT("vec_u8"), Db->VecU8); + RegisterTable(TEXT("one_simple_enum"), Db->OneSimpleEnum); + RegisterTable(TEXT("pk_u64"), Db->PkU64); + RegisterTable(TEXT("one_every_vec_struct"), Db->OneEveryVecStruct); RegisterTable(TEXT("pk_connection_id"), Db->PkConnectionId); - RegisterTable(TEXT("one_i16"), Db->OneI16); - RegisterTable(TEXT("large_table"), Db->LargeTable); - RegisterTable(TEXT("vec_enum_with_payload"), Db->VecEnumWithPayload); - RegisterTable(TEXT("one_i32"), Db->OneI32); - RegisterTable(TEXT("vec_f32"), Db->VecF32); - RegisterTable(TEXT("unique_connection_id"), Db->UniqueConnectionId); - RegisterTable(TEXT("option_simple_enum"), Db->OptionSimpleEnum); - RegisterTable(TEXT("vec_i256"), Db->VecI256); - RegisterTable(TEXT("vec_timestamp"), Db->VecTimestamp); - RegisterTable(TEXT("pk_i8"), Db->PkI8); - RegisterTable(TEXT("one_i256"), Db->OneI256); RegisterTable(TEXT("scheduled_table"), Db->ScheduledTable); - RegisterTable(TEXT("unique_u256"), Db->UniqueU256); - RegisterTable(TEXT("one_string"), Db->OneString); - RegisterTable(TEXT("vec_u16"), Db->VecU16); - RegisterTable(TEXT("vec_u256"), Db->VecU256); - RegisterTable(TEXT("option_string"), Db->OptionString); - RegisterTable(TEXT("one_u16"), Db->OneU16); - RegisterTable(TEXT("pk_identity"), Db->PkIdentity); - RegisterTable(TEXT("pk_u64"), Db->PkU64); - RegisterTable(TEXT("unique_i16"), Db->UniqueI16); - RegisterTable(TEXT("vec_every_primitive_struct"), Db->VecEveryPrimitiveStruct); - RegisterTable(TEXT("vec_u128"), Db->VecU128); - RegisterTable(TEXT("one_i8"), Db->OneI8); - RegisterTable(TEXT("unique_u8"), Db->UniqueU8); - RegisterTable(TEXT("vec_byte_struct"), Db->VecByteStruct); - RegisterTable(TEXT("one_u64"), Db->OneU64); + RegisterTable(TEXT("vec_i128"), Db->VecI128); + RegisterTable(TEXT("vec_u32"), Db->VecU32); + RegisterTable(TEXT("vec_unit_struct"), Db->VecUnitStruct); RegisterTable(TEXT("table_holds_table"), Db->TableHoldsTable); - RegisterTable(TEXT("unique_string"), Db->UniqueString); - RegisterTable(TEXT("one_timestamp"), Db->OneTimestamp); - RegisterTable(TEXT("vec_simple_enum"), Db->VecSimpleEnum); + RegisterTable(TEXT("vec_u64"), Db->VecU64); + RegisterTable(TEXT("one_identity"), Db->OneIdentity); + RegisterTable(TEXT("one_i256"), Db->OneI256); + RegisterTable(TEXT("one_u128"), Db->OneU128); RegisterTable(TEXT("option_i32"), Db->OptionI32); - RegisterTable(TEXT("pk_bool"), Db->PkBool); - RegisterTable(TEXT("pk_i256"), Db->PkI256); - RegisterTable(TEXT("one_every_vec_struct"), Db->OneEveryVecStruct); - RegisterTable(TEXT("unique_i64"), Db->UniqueI64); - RegisterTable(TEXT("unique_u32"), Db->UniqueU32); - RegisterTable(TEXT("pk_u16"), Db->PkU16); + RegisterTable(TEXT("one_f32"), Db->OneF32); + RegisterTable(TEXT("vec_enum_with_payload"), Db->VecEnumWithPayload); + RegisterTable(TEXT("one_i16"), Db->OneI16); + RegisterTable(TEXT("vec_i256"), Db->VecI256); + RegisterTable(TEXT("unique_i256"), Db->UniqueI256); + RegisterTable(TEXT("one_enum_with_payload"), Db->OneEnumWithPayload); + RegisterTable(TEXT("pk_simple_enum"), Db->PkSimpleEnum); + RegisterTable(TEXT("indexed_table"), Db->IndexedTable); + RegisterTable(TEXT("one_byte_struct"), Db->OneByteStruct); + RegisterTable(TEXT("one_u256"), Db->OneU256); + RegisterTable(TEXT("pk_identity"), Db->PkIdentity); + RegisterTable(TEXT("unique_i8"), Db->UniqueI8); + RegisterTable(TEXT("vec_i64"), Db->VecI64); + RegisterTable(TEXT("pk_bool"), Db->PkBool); + RegisterTable(TEXT("pk_u32"), Db->PkU32); RegisterTable(TEXT("one_connection_id"), Db->OneConnectionId); - RegisterTable(TEXT("one_i64"), Db->OneI64); + RegisterTable(TEXT("vec_string"), Db->VecString); + RegisterTable(TEXT("pk_u32_two"), Db->PkU32Two); + RegisterTable(TEXT("one_bool"), Db->OneBool); + RegisterTable(TEXT("pk_i64"), Db->PkI64); + RegisterTable(TEXT("one_u16"), Db->OneU16); + RegisterTable(TEXT("unique_string"), Db->UniqueString); + RegisterTable(TEXT("one_timestamp"), Db->OneTimestamp); + RegisterTable(TEXT("one_u8"), Db->OneU8); + RegisterTable(TEXT("vec_u128"), Db->VecU128); + RegisterTable(TEXT("vec_u256"), Db->VecU256); + RegisterTable(TEXT("vec_timestamp"), Db->VecTimestamp); + RegisterTable(TEXT("one_i8"), Db->OneI8); + RegisterTable(TEXT("pk_i32"), Db->PkI32); + RegisterTable(TEXT("unique_i64"), Db->UniqueI64); + RegisterTable(TEXT("option_every_primitive_struct"), Db->OptionEveryPrimitiveStruct); + RegisterTable(TEXT("one_u32"), Db->OneU32); + RegisterTable(TEXT("vec_identity"), Db->VecIdentity); + RegisterTable(TEXT("vec_byte_struct"), Db->VecByteStruct); + RegisterTable(TEXT("pk_i128"), Db->PkI128); + RegisterTable(TEXT("vec_i32"), Db->VecI32); + RegisterTable(TEXT("unique_connection_id"), Db->UniqueConnectionId); + RegisterTable(TEXT("unique_i16"), Db->UniqueI16); + RegisterTable(TEXT("large_table"), Db->LargeTable); + RegisterTable(TEXT("indexed_simple_enum"), Db->IndexedSimpleEnum); + RegisterTable(TEXT("one_i128"), Db->OneI128); + RegisterTable(TEXT("option_vec_option_i32"), Db->OptionVecOptionI32); + RegisterTable(TEXT("pk_i256"), Db->PkI256); + RegisterTable(TEXT("pk_u16"), Db->PkU16); + RegisterTable(TEXT("unique_identity"), Db->UniqueIdentity); + RegisterTable(TEXT("unique_u256"), Db->UniqueU256); RegisterTable(TEXT("unique_u64"), Db->UniqueU64); + RegisterTable(TEXT("one_string"), Db->OneString); + RegisterTable(TEXT("vec_i8"), Db->VecI8); + RegisterTable(TEXT("vec_simple_enum"), Db->VecSimpleEnum); + RegisterTable(TEXT("vec_i16"), Db->VecI16); + RegisterTable(TEXT("option_identity"), Db->OptionIdentity); + RegisterTable(TEXT("pk_u8"), Db->PkU8); + RegisterTable(TEXT("one_f64"), Db->OneF64); + RegisterTable(TEXT("one_every_primitive_struct"), Db->OneEveryPrimitiveStruct); + RegisterTable(TEXT("option_simple_enum"), Db->OptionSimpleEnum); + RegisterTable(TEXT("vec_u16"), Db->VecU16); + RegisterTable(TEXT("pk_u128"), Db->PkU128); + RegisterTable(TEXT("one_i32"), Db->OneI32); + RegisterTable(TEXT("users"), Db->Users); + RegisterTable(TEXT("unique_u16"), Db->UniqueU16); + RegisterTable(TEXT("indexed_table_2"), Db->IndexedTable2); + RegisterTable(TEXT("vec_connection_id"), Db->VecConnectionId); + RegisterTable(TEXT("one_i64"), Db->OneI64); + RegisterTable(TEXT("btree_u32"), Db->BtreeU32); RegisterTable(TEXT("pk_u256"), Db->PkU256); - RegisterTable(TEXT("vec_u8"), Db->VecU8); - RegisterTable(TEXT("vec_identity"), Db->VecIdentity); - RegisterTable(TEXT("one_u8"), Db->OneU8); + RegisterTable(TEXT("vec_bool"), Db->VecBool); + RegisterTable(TEXT("vec_f32"), Db->VecF32); RegisterTable(TEXT("vec_every_vec_struct"), Db->VecEveryVecStruct); - RegisterTable(TEXT("vec_unit_struct"), Db->VecUnitStruct); - RegisterTable(TEXT("one_bool"), Db->OneBool); - RegisterTable(TEXT("vec_string"), Db->VecString); - RegisterTable(TEXT("one_f32"), Db->OneF32); - RegisterTable(TEXT("option_identity"), Db->OptionIdentity); - RegisterTable(TEXT("vec_i8"), Db->VecI8); } FContextBase::FContextBase(UDbConnection* InConn) @@ -1333,205 +1333,205 @@ void URemoteTables::Initialize() { /** Creating tables */ - IndexedSimpleEnum = NewObject(this); - OneU128 = NewObject(this); - UniqueI8 = NewObject(this); - UniqueU16 = NewObject(this); - BtreeU32 = NewObject(this); - IndexedTable = NewObject(this); - OptionEveryPrimitiveStruct = NewObject(this); - UniqueI256 = NewObject(this); - OptionVecOptionI32 = NewObject(this); UniqueU128 = NewObject(this); - VecI128 = NewObject(this); - OneByteStruct = NewObject(this); - VecI32 = NewObject(this); - PkU32 = NewObject(this); - PkString = NewObject(this); - PkU128 = NewObject(this); - VecU64 = NewObject(this); - IndexedTable2 = NewObject(this); + OneU64 = NewObject(this); + PkI8 = NewObject(this); VecF64 = NewObject(this); - OneU256 = NewObject(this); - OneEveryPrimitiveStruct = NewObject(this); + UniqueBool = NewObject(this); UniqueI128 = NewObject(this); - VecI64 = NewObject(this); - PkU8 = NewObject(this); - OneF64 = NewObject(this); - VecU32 = NewObject(this); + OptionString = NewObject(this); PkI16 = NewObject(this); - PkI32 = NewObject(this); - OneU32 = NewObject(this); - UniqueBool = NewObject(this); - OneSimpleEnum = NewObject(this); - VecI16 = NewObject(this); - UniqueIdentity = NewObject(this); - PkU32Two = NewObject(this); - VecBool = NewObject(this); - OneEnumWithPayload = NewObject(this); - UniqueI32 = NewObject(this); - OneIdentity = NewObject(this); + UniqueU8 = NewObject(this); + VecEveryPrimitiveStruct = NewObject(this); OneUnitStruct = NewObject(this); - Users = NewObject(this); - VecConnectionId = NewObject(this); - PkI128 = NewObject(this); - PkSimpleEnum = NewObject(this); - PkI64 = NewObject(this); - OneI128 = NewObject(this); + PkString = NewObject(this); + UniqueI32 = NewObject(this); + UniqueU32 = NewObject(this); + VecU8 = NewObject(this); + OneSimpleEnum = NewObject(this); + PkU64 = NewObject(this); + OneEveryVecStruct = NewObject(this); PkConnectionId = NewObject(this); - OneI16 = NewObject(this); - LargeTable = NewObject(this); + ScheduledTable = NewObject(this); + VecI128 = NewObject(this); + VecU32 = NewObject(this); + VecUnitStruct = NewObject(this); + TableHoldsTable = NewObject(this); + VecU64 = NewObject(this); + OneIdentity = NewObject(this); + OneI256 = NewObject(this); + OneU128 = NewObject(this); + OptionI32 = NewObject(this); + OneF32 = NewObject(this); VecEnumWithPayload = NewObject(this); - OneI32 = NewObject(this); - VecF32 = NewObject(this); - UniqueConnectionId = NewObject(this); - OptionSimpleEnum = NewObject(this); + OneI16 = NewObject(this); VecI256 = NewObject(this); - VecTimestamp = NewObject(this); - PkI8 = NewObject(this); - OneI256 = NewObject(this); - ScheduledTable = NewObject(this); - UniqueU256 = NewObject(this); - OneString = NewObject(this); - VecU16 = NewObject(this); - VecU256 = NewObject(this); - OptionString = NewObject(this); - OneU16 = NewObject(this); + UniqueI256 = NewObject(this); + OneEnumWithPayload = NewObject(this); + PkSimpleEnum = NewObject(this); + IndexedTable = NewObject(this); + OneByteStruct = NewObject(this); + OneU256 = NewObject(this); PkIdentity = NewObject(this); - PkU64 = NewObject(this); - UniqueI16 = NewObject(this); - VecEveryPrimitiveStruct = NewObject(this); + UniqueI8 = NewObject(this); + VecI64 = NewObject(this); + PkBool = NewObject(this); + PkU32 = NewObject(this); + OneConnectionId = NewObject(this); + VecString = NewObject(this); + PkU32Two = NewObject(this); + OneBool = NewObject(this); + PkI64 = NewObject(this); + OneU16 = NewObject(this); + UniqueString = NewObject(this); + OneTimestamp = NewObject(this); + OneU8 = NewObject(this); VecU128 = NewObject(this); + VecU256 = NewObject(this); + VecTimestamp = NewObject(this); OneI8 = NewObject(this); - UniqueU8 = NewObject(this); + PkI32 = NewObject(this); + UniqueI64 = NewObject(this); + OptionEveryPrimitiveStruct = NewObject(this); + OneU32 = NewObject(this); + VecIdentity = NewObject(this); VecByteStruct = NewObject(this); - OneU64 = NewObject(this); - TableHoldsTable = NewObject(this); - UniqueString = NewObject(this); - OneTimestamp = NewObject(this); - VecSimpleEnum = NewObject(this); - OptionI32 = NewObject(this); - PkBool = NewObject(this); + PkI128 = NewObject(this); + VecI32 = NewObject(this); + UniqueConnectionId = NewObject(this); + UniqueI16 = NewObject(this); + LargeTable = NewObject(this); + IndexedSimpleEnum = NewObject(this); + OneI128 = NewObject(this); + OptionVecOptionI32 = NewObject(this); PkI256 = NewObject(this); - OneEveryVecStruct = NewObject(this); - UniqueI64 = NewObject(this); - UniqueU32 = NewObject(this); PkU16 = NewObject(this); - OneConnectionId = NewObject(this); - OneI64 = NewObject(this); + UniqueIdentity = NewObject(this); + UniqueU256 = NewObject(this); UniqueU64 = NewObject(this); + OneString = NewObject(this); + VecI8 = NewObject(this); + VecSimpleEnum = NewObject(this); + VecI16 = NewObject(this); + OptionIdentity = NewObject(this); + PkU8 = NewObject(this); + OneF64 = NewObject(this); + OneEveryPrimitiveStruct = NewObject(this); + OptionSimpleEnum = NewObject(this); + VecU16 = NewObject(this); + PkU128 = NewObject(this); + OneI32 = NewObject(this); + Users = NewObject(this); + UniqueU16 = NewObject(this); + IndexedTable2 = NewObject(this); + VecConnectionId = NewObject(this); + OneI64 = NewObject(this); + BtreeU32 = NewObject(this); PkU256 = NewObject(this); - VecU8 = NewObject(this); - VecIdentity = NewObject(this); - OneU8 = NewObject(this); + VecBool = NewObject(this); + VecF32 = NewObject(this); VecEveryVecStruct = NewObject(this); - VecUnitStruct = NewObject(this); - OneBool = NewObject(this); - VecString = NewObject(this); - OneF32 = NewObject(this); - OptionIdentity = NewObject(this); - VecI8 = NewObject(this); /**/ /** Initialization */ - IndexedSimpleEnum->PostInitialize(); - OneU128->PostInitialize(); - UniqueI8->PostInitialize(); - UniqueU16->PostInitialize(); - BtreeU32->PostInitialize(); - IndexedTable->PostInitialize(); - OptionEveryPrimitiveStruct->PostInitialize(); - UniqueI256->PostInitialize(); - OptionVecOptionI32->PostInitialize(); UniqueU128->PostInitialize(); - VecI128->PostInitialize(); - OneByteStruct->PostInitialize(); - VecI32->PostInitialize(); - PkU32->PostInitialize(); - PkString->PostInitialize(); - PkU128->PostInitialize(); - VecU64->PostInitialize(); - IndexedTable2->PostInitialize(); + OneU64->PostInitialize(); + PkI8->PostInitialize(); VecF64->PostInitialize(); - OneU256->PostInitialize(); - OneEveryPrimitiveStruct->PostInitialize(); + UniqueBool->PostInitialize(); UniqueI128->PostInitialize(); - VecI64->PostInitialize(); - PkU8->PostInitialize(); - OneF64->PostInitialize(); - VecU32->PostInitialize(); + OptionString->PostInitialize(); PkI16->PostInitialize(); - PkI32->PostInitialize(); - OneU32->PostInitialize(); - UniqueBool->PostInitialize(); - OneSimpleEnum->PostInitialize(); - VecI16->PostInitialize(); - UniqueIdentity->PostInitialize(); - PkU32Two->PostInitialize(); - VecBool->PostInitialize(); - OneEnumWithPayload->PostInitialize(); - UniqueI32->PostInitialize(); - OneIdentity->PostInitialize(); + UniqueU8->PostInitialize(); + VecEveryPrimitiveStruct->PostInitialize(); OneUnitStruct->PostInitialize(); - Users->PostInitialize(); - VecConnectionId->PostInitialize(); - PkI128->PostInitialize(); - PkSimpleEnum->PostInitialize(); - PkI64->PostInitialize(); - OneI128->PostInitialize(); + PkString->PostInitialize(); + UniqueI32->PostInitialize(); + UniqueU32->PostInitialize(); + VecU8->PostInitialize(); + OneSimpleEnum->PostInitialize(); + PkU64->PostInitialize(); + OneEveryVecStruct->PostInitialize(); PkConnectionId->PostInitialize(); - OneI16->PostInitialize(); - LargeTable->PostInitialize(); + ScheduledTable->PostInitialize(); + VecI128->PostInitialize(); + VecU32->PostInitialize(); + VecUnitStruct->PostInitialize(); + TableHoldsTable->PostInitialize(); + VecU64->PostInitialize(); + OneIdentity->PostInitialize(); + OneI256->PostInitialize(); + OneU128->PostInitialize(); + OptionI32->PostInitialize(); + OneF32->PostInitialize(); VecEnumWithPayload->PostInitialize(); - OneI32->PostInitialize(); - VecF32->PostInitialize(); - UniqueConnectionId->PostInitialize(); - OptionSimpleEnum->PostInitialize(); + OneI16->PostInitialize(); VecI256->PostInitialize(); - VecTimestamp->PostInitialize(); - PkI8->PostInitialize(); - OneI256->PostInitialize(); - ScheduledTable->PostInitialize(); - UniqueU256->PostInitialize(); - OneString->PostInitialize(); - VecU16->PostInitialize(); - VecU256->PostInitialize(); - OptionString->PostInitialize(); - OneU16->PostInitialize(); + UniqueI256->PostInitialize(); + OneEnumWithPayload->PostInitialize(); + PkSimpleEnum->PostInitialize(); + IndexedTable->PostInitialize(); + OneByteStruct->PostInitialize(); + OneU256->PostInitialize(); PkIdentity->PostInitialize(); - PkU64->PostInitialize(); - UniqueI16->PostInitialize(); - VecEveryPrimitiveStruct->PostInitialize(); + UniqueI8->PostInitialize(); + VecI64->PostInitialize(); + PkBool->PostInitialize(); + PkU32->PostInitialize(); + OneConnectionId->PostInitialize(); + VecString->PostInitialize(); + PkU32Two->PostInitialize(); + OneBool->PostInitialize(); + PkI64->PostInitialize(); + OneU16->PostInitialize(); + UniqueString->PostInitialize(); + OneTimestamp->PostInitialize(); + OneU8->PostInitialize(); VecU128->PostInitialize(); + VecU256->PostInitialize(); + VecTimestamp->PostInitialize(); OneI8->PostInitialize(); - UniqueU8->PostInitialize(); + PkI32->PostInitialize(); + UniqueI64->PostInitialize(); + OptionEveryPrimitiveStruct->PostInitialize(); + OneU32->PostInitialize(); + VecIdentity->PostInitialize(); VecByteStruct->PostInitialize(); - OneU64->PostInitialize(); - TableHoldsTable->PostInitialize(); - UniqueString->PostInitialize(); - OneTimestamp->PostInitialize(); - VecSimpleEnum->PostInitialize(); - OptionI32->PostInitialize(); - PkBool->PostInitialize(); + PkI128->PostInitialize(); + VecI32->PostInitialize(); + UniqueConnectionId->PostInitialize(); + UniqueI16->PostInitialize(); + LargeTable->PostInitialize(); + IndexedSimpleEnum->PostInitialize(); + OneI128->PostInitialize(); + OptionVecOptionI32->PostInitialize(); PkI256->PostInitialize(); - OneEveryVecStruct->PostInitialize(); - UniqueI64->PostInitialize(); - UniqueU32->PostInitialize(); PkU16->PostInitialize(); - OneConnectionId->PostInitialize(); - OneI64->PostInitialize(); + UniqueIdentity->PostInitialize(); + UniqueU256->PostInitialize(); UniqueU64->PostInitialize(); + OneString->PostInitialize(); + VecI8->PostInitialize(); + VecSimpleEnum->PostInitialize(); + VecI16->PostInitialize(); + OptionIdentity->PostInitialize(); + PkU8->PostInitialize(); + OneF64->PostInitialize(); + OneEveryPrimitiveStruct->PostInitialize(); + OptionSimpleEnum->PostInitialize(); + VecU16->PostInitialize(); + PkU128->PostInitialize(); + OneI32->PostInitialize(); + Users->PostInitialize(); + UniqueU16->PostInitialize(); + IndexedTable2->PostInitialize(); + VecConnectionId->PostInitialize(); + OneI64->PostInitialize(); + BtreeU32->PostInitialize(); PkU256->PostInitialize(); - VecU8->PostInitialize(); - VecIdentity->PostInitialize(); - OneU8->PostInitialize(); + VecBool->PostInitialize(); + VecF32->PostInitialize(); VecEveryVecStruct->PostInitialize(); - VecUnitStruct->PostInitialize(); - OneBool->PostInitialize(); - VecString->PostInitialize(); - OneF32->PostInitialize(); - OptionIdentity->PostInitialize(); - VecI8->PostInitialize(); /**/ } diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalInt32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalInt32.g.h index 3fcc5bfdda0..42ef3455607 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalInt32.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalInt32.g.h @@ -15,7 +15,7 @@ struct TESTCLIENT_API FTestClientOptionalInt32 bool bHasValue = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bHasValue")) - int32 Value; + int32 Value = 0; FTestClientOptionalInt32() = default; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalSimpleEnum.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalSimpleEnum.g.h index 4889acee798..237f4fc0e1c 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalSimpleEnum.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalSimpleEnum.g.h @@ -16,7 +16,7 @@ struct TESTCLIENT_API FTestClientOptionalSimpleEnum bool bHasValue = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB", meta = (EditCondition = "bHasValue")) - ESimpleEnumType Value; + ESimpleEnumType Value = static_cast(0); FTestClientOptionalSimpleEnum() = default; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalVecOptionalInt32.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalVecOptionalInt32.g.h index 5b896723bc1..e024d59c1c2 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalVecOptionalInt32.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Optionals/TestClientOptionalVecOptionalInt32.g.h @@ -4,6 +4,7 @@ #pragma once #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" +#include "ModuleBindings/Optionals/TestClientOptionalInt32.g.h" #include "TestClientOptionalVecOptionalInt32.g.generated.h" USTRUCT(BlueprintType) diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h index 929f0949693..f2f63f89361 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/SpacetimeDBClient.g.h @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 1.5.0 (commit 4a57de1003025dd579c6e22bb49bd56e2aa27ff2). +// This was generated using spacetimedb cli version 1.6.0 (commit 82fbf61156c909b31f12c7d2a4625b60e28d44c8). #pragma once #include "CoreMinimal.h" @@ -6888,298 +6888,298 @@ class TESTCLIENT_API URemoteTables : public UObject void Initialize(); UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UIndexedSimpleEnumTable* IndexedSimpleEnum; + UUniqueU128Table* UniqueU128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU128Table* OneU128; + UOneU64Table* OneU64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueI8Table* UniqueI8; + UPkI8Table* PkI8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU16Table* UniqueU16; + UVecF64Table* VecF64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UBTreeU32Table* BtreeU32; + UUniqueBoolTable* UniqueBool; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UIndexedTableTable* IndexedTable; + UUniqueI128Table* UniqueI128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionEveryPrimitiveStructTable* OptionEveryPrimitiveStruct; + UOptionStringTable* OptionString; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueI256Table* UniqueI256; + UPkI16Table* PkI16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionVecOptionI32Table* OptionVecOptionI32; + UUniqueU8Table* UniqueU8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU128Table* UniqueU128; + UVecEveryPrimitiveStructTable* VecEveryPrimitiveStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI128Table* VecI128; + UOneUnitStructTable* OneUnitStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneByteStructTable* OneByteStruct; + UPkStringTable* PkString; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI32Table* VecI32; + UUniqueI32Table* UniqueI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU32Table* PkU32; + UUniqueU32Table* UniqueU32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkStringTable* PkString; + UVecU8Table* VecU8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU128Table* PkU128; + UOneSimpleEnumTable* OneSimpleEnum; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU64Table* VecU64; + UPkU64Table* PkU64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UIndexedTable2Table* IndexedTable2; + UOneEveryVecStructTable* OneEveryVecStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecF64Table* VecF64; + UPkConnectionIdTable* PkConnectionId; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU256Table* OneU256; + UScheduledTableTable* ScheduledTable; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneEveryPrimitiveStructTable* OneEveryPrimitiveStruct; + UVecI128Table* VecI128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueI128Table* UniqueI128; + UVecU32Table* VecU32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI64Table* VecI64; + UVecUnitStructTable* VecUnitStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU8Table* PkU8; + UTableHoldsTableTable* TableHoldsTable; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneF64Table* OneF64; + UVecU64Table* VecU64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU32Table* VecU32; + UOneIdentityTable* OneIdentity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI16Table* PkI16; + UOneI256Table* OneI256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI32Table* PkI32; + UOneU128Table* OneU128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU32Table* OneU32; + UOptionI32Table* OptionI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueBoolTable* UniqueBool; + UOneF32Table* OneF32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneSimpleEnumTable* OneSimpleEnum; + UVecEnumWithPayloadTable* VecEnumWithPayload; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI16Table* VecI16; + UOneI16Table* OneI16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueIdentityTable* UniqueIdentity; + UVecI256Table* VecI256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU32TwoTable* PkU32Two; + UUniqueI256Table* UniqueI256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecBoolTable* VecBool; + UOneEnumWithPayloadTable* OneEnumWithPayload; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneEnumWithPayloadTable* OneEnumWithPayload; + UPkSimpleEnumTable* PkSimpleEnum; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueI32Table* UniqueI32; + UIndexedTableTable* IndexedTable; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneIdentityTable* OneIdentity; + UOneByteStructTable* OneByteStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneUnitStructTable* OneUnitStruct; + UOneU256Table* OneU256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUsersTable* Users; + UPkIdentityTable* PkIdentity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecConnectionIdTable* VecConnectionId; + UUniqueI8Table* UniqueI8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI128Table* PkI128; + UVecI64Table* VecI64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkSimpleEnumTable* PkSimpleEnum; + UPkBoolTable* PkBool; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI64Table* PkI64; + UPkU32Table* PkU32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI128Table* OneI128; + UOneConnectionIdTable* OneConnectionId; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkConnectionIdTable* PkConnectionId; + UVecStringTable* VecString; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI16Table* OneI16; + UPkU32TwoTable* PkU32Two; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - ULargeTableTable* LargeTable; + UOneBoolTable* OneBool; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecEnumWithPayloadTable* VecEnumWithPayload; + UPkI64Table* PkI64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI32Table* OneI32; + UOneU16Table* OneU16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecF32Table* VecF32; + UUniqueStringTable* UniqueString; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueConnectionIdTable* UniqueConnectionId; + UOneTimestampTable* OneTimestamp; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionSimpleEnumTable* OptionSimpleEnum; + UOneU8Table* OneU8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI256Table* VecI256; + UVecU128Table* VecU128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecTimestampTable* VecTimestamp; + UVecU256Table* VecU256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI8Table* PkI8; + UVecTimestampTable* VecTimestamp; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI256Table* OneI256; + UOneI8Table* OneI8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UScheduledTableTable* ScheduledTable; + UPkI32Table* PkI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU256Table* UniqueU256; + UUniqueI64Table* UniqueI64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneStringTable* OneString; + UOptionEveryPrimitiveStructTable* OptionEveryPrimitiveStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU16Table* VecU16; + UOneU32Table* OneU32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU256Table* VecU256; + UVecIdentityTable* VecIdentity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionStringTable* OptionString; + UVecByteStructTable* VecByteStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU16Table* OneU16; + UPkI128Table* PkI128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkIdentityTable* PkIdentity; + UVecI32Table* VecI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU64Table* PkU64; + UUniqueConnectionIdTable* UniqueConnectionId; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") UUniqueI16Table* UniqueI16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecEveryPrimitiveStructTable* VecEveryPrimitiveStruct; + ULargeTableTable* LargeTable; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU128Table* VecU128; + UIndexedSimpleEnumTable* IndexedSimpleEnum; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI8Table* OneI8; + UOneI128Table* OneI128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU8Table* UniqueU8; + UOptionVecOptionI32Table* OptionVecOptionI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecByteStructTable* VecByteStruct; + UPkI256Table* PkI256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU64Table* OneU64; + UPkU16Table* PkU16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UTableHoldsTableTable* TableHoldsTable; + UUniqueIdentityTable* UniqueIdentity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueStringTable* UniqueString; + UUniqueU256Table* UniqueU256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneTimestampTable* OneTimestamp; + UUniqueU64Table* UniqueU64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecSimpleEnumTable* VecSimpleEnum; + UOneStringTable* OneString; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionI32Table* OptionI32; + UVecI8Table* VecI8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkBoolTable* PkBool; + UVecSimpleEnumTable* VecSimpleEnum; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkI256Table* PkI256; + UVecI16Table* VecI16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneEveryVecStructTable* OneEveryVecStruct; + UOptionIdentityTable* OptionIdentity; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueI64Table* UniqueI64; + UPkU8Table* PkU8; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU32Table* UniqueU32; + UOneF64Table* OneF64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU16Table* PkU16; + UOneEveryPrimitiveStructTable* OneEveryPrimitiveStruct; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneConnectionIdTable* OneConnectionId; + UOptionSimpleEnumTable* OptionSimpleEnum; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneI64Table* OneI64; + UVecU16Table* VecU16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UUniqueU64Table* UniqueU64; + UPkU128Table* PkU128; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UPkU256Table* PkU256; + UOneI32Table* OneI32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecU8Table* VecU8; + UUsersTable* Users; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecIdentityTable* VecIdentity; + UUniqueU16Table* UniqueU16; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneU8Table* OneU8; + UIndexedTable2Table* IndexedTable2; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecEveryVecStructTable* VecEveryVecStruct; + UVecConnectionIdTable* VecConnectionId; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecUnitStructTable* VecUnitStruct; + UOneI64Table* OneI64; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneBoolTable* OneBool; + UBTreeU32Table* BtreeU32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecStringTable* VecString; + UPkU256Table* PkU256; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOneF32Table* OneF32; + UVecBoolTable* VecBool; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UOptionIdentityTable* OptionIdentity; + UVecF32Table* VecF32; UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB") - UVecI8Table* VecI8; + UVecEveryVecStructTable* VecEveryVecStruct; }; @@ -9738,7 +9738,7 @@ class TESTCLIENT_API UDbConnection : public UDbConnectionBase USubscriptionBuilder* SubscriptionBuilder(); /** Static entry point for constructing a connection. */ - UFUNCTION(BlueprintCallable, Category = "SpacetimeDB", DisplayName = "SpacetimeDB Builder") + UFUNCTION(BlueprintCallable, Category = "SpacetimeDB", DisplayName = "SpacetimeDB TestClient Builder") static UDbConnectionBuilder* Builder(); // Error handling @@ -9747,6 +9747,8 @@ class TESTCLIENT_API UDbConnection : public UDbConnectionBase FOnUnhandledReducerError OnUnhandledReducerError; + friend USubscriptionBuilder; + friend UDbConnectionBuilder; protected: // Hook up error handling to reducers diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h index 40f8b284a02..26e14fc1484 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/EnumWithPayloadType.g.h @@ -4,9 +4,9 @@ #pragma once #include "CoreMinimal.h" #include "BSATN/UESpacetimeDB.h" -#include "Types/Builtins.h" #include "ModuleBindings/Types/SimpleEnumType.g.h" #include "Kismet/BlueprintFunctionLibrary.h" +#include "Types/Builtins.h" #include "EnumWithPayloadType.g.generated.h" UENUM(BlueprintType) @@ -45,7 +45,7 @@ struct TESTCLIENT_API FEnumWithPayloadType public: FEnumWithPayloadType() = default; - TVariant, uint8, TArray, FSpacetimeDBTimestamp, FSpacetimeDBConnectionId, TArray, float, FSpacetimeDBUInt128, uint64, FSpacetimeDBInt256, FString, FSpacetimeDBIdentity, TArray> MessageData; + TVariant, int8, FSpacetimeDBInt256, uint64, FSpacetimeDBUInt256, float, int16, FSpacetimeDBTimestamp, uint32, FSpacetimeDBIdentity, TArray, FSpacetimeDBUInt128, TArray, uint8, int32, double, int64, FString, TArray> MessageData; UPROPERTY(BlueprintReadOnly) EEnumWithPayloadTag Tag = static_cast(0); diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/IndexedSimpleEnumType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/IndexedSimpleEnumType.g.h index d37a8371a2c..da6b82dbd05 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/IndexedSimpleEnumType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/IndexedSimpleEnumType.g.h @@ -13,7 +13,7 @@ struct TESTCLIENT_API FIndexedSimpleEnumType GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") - ESimpleEnumType N; + ESimpleEnumType N = static_cast(0); FORCEINLINE bool operator==(const FIndexedSimpleEnumType& Other) const { diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/LargeTableType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/LargeTableType.g.h index 35083fecceb..41e216e21e6 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/LargeTableType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/LargeTableType.g.h @@ -67,7 +67,7 @@ struct TESTCLIENT_API FLargeTableType FString P; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") - ESimpleEnumType Q; + ESimpleEnumType Q = static_cast(0); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") FEnumWithPayloadType R; diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/OneSimpleEnumType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/OneSimpleEnumType.g.h index 420cb2ef7b1..757e2c3b8f1 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/OneSimpleEnumType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/OneSimpleEnumType.g.h @@ -13,7 +13,7 @@ struct TESTCLIENT_API FOneSimpleEnumType GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") - ESimpleEnumType E; + ESimpleEnumType E = static_cast(0); FORCEINLINE bool operator==(const FOneSimpleEnumType& Other) const { diff --git a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/PkSimpleEnumType.g.h b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/PkSimpleEnumType.g.h index a04e272c23f..adac377cb4a 100644 --- a/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/PkSimpleEnumType.g.h +++ b/sdks/unreal/tests/TestClient/Source/TestClient/Public/ModuleBindings/Types/PkSimpleEnumType.g.h @@ -13,7 +13,7 @@ struct TESTCLIENT_API FPkSimpleEnumType GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") - ESimpleEnumType A; + ESimpleEnumType A = static_cast(0); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpacetimeDB") int32 Data = 0;