From f950111be1e3171bf591e8e4f018518cd8530caf Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Thu, 7 May 2026 21:49:11 -0400 Subject: [PATCH 1/7] 0.24.5 DLL --- SimConnect.dll | Bin 67072 -> 67072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/SimConnect.dll b/SimConnect.dll index 2aa284c02b3a18123fd0ae619d1bcd35334b254d..8f0fe287bf12976fd86e0b41ec827fb98367c862 100644 GIT binary patch delta 6981 zcmeI0Yj{-ExyRp`Ok#k*nLq#`K|&2T36w%aE`kZ+l4!6)62yY`WXKF8$4N3y28aku zu$05GfYA*W6)-&o%0aY|aI*(BRFI1x18U28sxneak(&{*MGJC%Yu1`H&6o4_d}yBM z&+ot9^{&0wW$!&}QM%-e=eG zk@kdW{^+(z%o*mjQ$u&{Lvn)ZL zIedSam10}iuJ(dR_P>ZUSufarW&5--$DTgQHmGsdm_N+5-PSnn^?PnhJlIntZ{^q~ zYtf#p#Funob>ka*CdY?d-|1V7H!LxX-FU6T7PX5F%M1$)M;h)hOfb9wPOZ7}3{r-68Ti3R?T#zo+kB6Ae!m8I&iY%gp!LL}`gxy^i

=Y#P3>5RhAlZnP4N1~Gnv1eKN zAKaH*KtMe?;qQrjg9@w{K1j6{SUW#BK6t`8Q@2Z`?{40kXgNXT8am6%7EF?Gtj>D< z!za65QyI~T=^%aPi{v1&az5&E|LuR)*HV#bC{}LCiq<=#3oFHmQa_J;@}gJdB7ZM8 zZuqF1-PZ8)AJ}YNtn@>U_F>+t>nQ!gvwgZ*u0sy1`S%O$Wf!bf2fK~Z6c`MZv>knfzC<0q;5|e$(K7T3I)W~vcwX^- zXgXSmUP8OjDfBsVe#u&(0`xd~7HvgGPy~I8oL5B#UX_sKVM@`HXdP-o=aBO&k^U$L z%|tb5IogEwp-+)qqa$cC@}Zxh*U)?D3)Jyzk-_Kz9ScQsza{uE!J1Zy@7ioqPwY^u*ePPoD%R@vHG|*AX4UCdu?fU#iPf}si zdFAXX*<=m6bWiW8_CoKRTwhhS_W|z{vP6}B==WAqm{^k|tE?rL`uyvwc2`w(aEiCO z+C9gc!Z-YO0|AN?$^#@<1)d;&(&VX*T~9^6Fq7 zSyJD4@oHC_<%~<;el5`+N{sMjPZpVqJnVr>;0Gv!cmxjb!sZm84R<4z)3PVVx85(S zee}KEL_Q?0I0>D{D^5n&@h!^sphIHMa z33l$I4=d^Lx9kFiU17_P5U+NIi5cYJ6+59IUNHqN#izs7eGwbidiXI?TkQx;3-!|l z7ktY2I{1b0PWH9Yz3o}eQU^Qj72U@$HF(9*=o&s7-b88yaxY)5v3g`JCluo9N zAX<)BT#7d06`w(S@J;a8cm_a+!sA11U2}OVnZ^j5Iziv81l}-SCW;iI{WNHOXlZ?* zQ3suMsDvEFCKSXg9z;v=VK{j*gW_H;=ttW^5p9-G*nzKuzc9W5?lV3NV@FFxM?M!M zU$G}Ti&yM}uHhB?o4Dd&6CVl#NZm`FkV4TT5V3d^m}p zVbxI=>|CLrv-A+=0#Y|?hNt)yRXzeo`1NSAVaLaH+zET|%e;=+N{0ihwI2%ao~uWh z4Li-#v*m96L6KqUXr@=0wWqTc1PKd2}VpB(AsyW#bk93%T%$4X6aK z7)CXC#Va*>s+(cl0yFJ!#gn?Dbx-pCCoR$iCmg?6dly{I(nKE?xV%=6z79URM31Zl zI)1_#gPCx`PmucRMc`LU_08m`9MG5PX&(xw{k!%huyDEZT)YG`_&;>xq41{h@-#=( zpP5d;u`9LDhTB*1YsM&>;O1xaMH}GOXLU{kJZ{k$Iv0k2T&+9gUnBC|^Lkn9;isXW z^S-L}hVQK9bvjQ2xc&v*p?X;HqV|3`_9gAJVaIjaJK^#5+(1n`d~t)Gt$JATvS|w+ zsyCyD)xXdk3e{pZ{3j0{jqBltU+ScKcxt2e5qM~mzGxV}xY^tQF8`HT8n|GK&aZ`2 zx9V5A1YUZDZv->Z4BNk|XUGY!zsmZnr(IqX$^SL$NRkWYHy95`ysmvVoUvUuE`fQC z`o=EUd53wO;2Gna;hQ`4=$qi-UHVOF`Hvay)ps}R|K4ss1QZlMLVmpBB~*)7{F{m2 zfFt+l*C`Kr(T)h;2>1@lWcecSJ2Vn6Z}8bh>h;Tnub_L0Z-Y0`ju4HN>HObxf{GNl z7S-Vu5AWr3j6Vw7y{SJenXmwDqir!vA}r6HAr=IExhx$Q6G{F z%wCj5?-V1tBFc8}=mu$U&VEKkP8r;Y)Sf^wV!Yy#cllu$&XfwR$aydSPb t6L{vr@bba?n1;`orbFy>k@AWK#w(T>ulPJl;zEkAq2k^AZ`*Ol{{np8qt^fc delta 6920 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 From a3c97a616b6950bc61ae0fbda76f727a8bf6b7b9 Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Fri, 8 May 2026 00:28:12 -0400 Subject: [PATCH 2/7] Readme corrections --- Readme.md | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Readme.md b/Readme.md index c960e92..90da561 100644 --- a/Readme.md +++ b/Readme.md @@ -2,12 +2,18 @@ # SimConnect Bindings for Rust -## Requirements +This crate provides Rust bindings to receive and send information through SimConnect, for Microsoft Flight Simulator (2020). -- [CLang](https://clang.llvm.org/get_started.html) (See the [Rust Bindgen Documentation](https://rust-lang.github.io/rust-bindgen/requirements.html)) -- MSVC x64 Rust build (`x86_64-pc-windows-msvc`, see [The rustup book](https://rust-lang.github.io/rustup/installation/windows.html)) +Documentation can be found at: [MSFS 2020 SDK](https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/SimConnect_SDK.htm) -## Using +### Requirements + +- [Rust](https://rust-lang.org/learn/get-started) +- [LLVM/Clang](https://clang.llvm.org/get_started.html) + +See the [Rust Bindgen Documentation](https://rust-lang.github.io/rust-bindgen/introduction.html) + +### Using Add this to your `Cargo.toml` @@ -16,14 +22,16 @@ Add this to your `Cargo.toml` simconnect = "0.4" ``` -## Building +_You must have SimConnect.dll in the same directory as your executable._ + +### Building _The SimConnect binaries are included within this repository, but they may not be up-to-date._ -1. run `cargo build` -2. Add `use simconnect` at the top of your file +1. Run `cargo build` +2. Add import `use simconnect` at the top of your file -## Example +### Examples Read float position data @@ -31,14 +39,12 @@ Read float position data cargo run --example aircraft_updates ``` -Requests tagged data with thresholds from SimConnect and reads floats/strings +Requests tagged data with thresholds from SimConnect, and reads floats/strings ``` cargo run --example aircraft_updates_on_change ``` -_You must have SimConnect.dll in the same directory as the compiled exe for it to run (e.g. in )_ - ### Remarks -I have not tested every single function from the api. If you find an error, feel free to make an issue or a pull request. +I have not tested every function of the API. If you find an error, feel free to make an issue or pull request. From 2b510fcafb32768c731fa190ff3eac9e33e235fe Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Fri, 8 May 2026 00:49:17 -0400 Subject: [PATCH 3/7] Fix example typos --- examples/aircraft_updates/main.rs | 8 ++++---- examples/aircraft_updates_on_change/main.rs | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/aircraft_updates/main.rs b/examples/aircraft_updates/main.rs index 5e6eedf..44ae0ce 100644 --- a/examples/aircraft_updates/main.rs +++ b/examples/aircraft_updates/main.rs @@ -1,6 +1,5 @@ use std::thread::sleep; use std::time::Duration; - use simconnect::DispatchResult; struct DataStruct { @@ -8,9 +7,10 @@ struct DataStruct { lon: f64, alt: f64, } + fn main() { let mut conn = simconnect::SimConnector::new(); - conn.connect("Simple Program"); // Intialize connection with SimConnect + conn.connect("Simple Program"); // Initialize connection with SimConnect conn.add_data_definition( 0, "PLANE LATITUDE", @@ -34,7 +34,7 @@ fn main() { simconnect::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_FLOAT64, u32::MAX, 1.0, - ); //define_id, units, data_type, datum_id, epsilon (update threshold) + ); // define_id, units, data_type, datum_id, epsilon (update threshold) conn.request_data_on_sim_object( 0, 0, @@ -44,7 +44,7 @@ fn main() { 0, 0, 0, - ); //request_id, define_id, object_id (user), period, falgs, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft + ); // request_id, define_id, object_id (user), period, flags, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft loop { match conn.get_next_message() { diff --git a/examples/aircraft_updates_on_change/main.rs b/examples/aircraft_updates_on_change/main.rs index f4211a0..4e51592 100644 --- a/examples/aircraft_updates_on_change/main.rs +++ b/examples/aircraft_updates_on_change/main.rs @@ -1,9 +1,9 @@ -use simconnect::{DispatchResult, DWORD}; use std::ptr::read_unaligned; use std::thread::sleep; use std::time::Duration; +use simconnect::{DispatchResult, DWORD}; -// To allign the memory we have to set a fixed max size to the returned variables from the game +// To align the memory we have to set a fixed max size to the returned variables from the game const MAX_RETURNED_ITEMS: usize = 255; // Rust will add padding to the inner parts of a struct if it isn't marked as packed @@ -54,7 +54,7 @@ fn main() { simconnect::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_FLOAT64, 3, 100.0, - ); //define_id, units, data_type, datum_id, epsilon (update threshold) + ); // define_id, units, data_type, datum_id, epsilon (update threshold) // Here we define all our variabes that get returned as Strings // Notice how the define_id differs from the float values @@ -82,7 +82,7 @@ fn main() { 0, 0, 0, - ); //request_id, define_id, object_id (user), period, falgs, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft + ); // request_id, define_id, object_id (user), period, flags, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft // Request the data from our define_id 1 (strings) // The request_id has to differ from the float request. Or else it will overwrite the previous request conn.request_data_on_sim_object( @@ -95,7 +95,7 @@ fn main() { 0, 0, 0, - ); //request_id, define_id, object_id (user), period, falgs, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft + ); // request_id, define_id, object_id (user), period, flags, origin, interval, limit - tells simconnect to send data for the defined id and on the user aircraft loop { match conn.get_next_message() { From 93c4cd5d02cf042164ec2cb937930bb1d8a5df0a Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Fri, 8 May 2026 00:55:50 -0400 Subject: [PATCH 4/7] tweaks --- Readme.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index 90da561..24ee76b 100644 --- a/Readme.md +++ b/Readme.md @@ -2,18 +2,20 @@ # SimConnect Bindings for Rust -This crate provides Rust bindings to receive and send information through SimConnect, for Microsoft Flight Simulator (2020). +This crate provides Rust bindings to send/receive information through SimConnect, for Microsoft Flight Simulator (2020). Documentation can be found at: [MSFS 2020 SDK](https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/SimConnect_SDK.htm) -### Requirements + +## Requirements - [Rust](https://rust-lang.org/learn/get-started) - [LLVM/Clang](https://clang.llvm.org/get_started.html) See the [Rust Bindgen Documentation](https://rust-lang.github.io/rust-bindgen/introduction.html) -### Using + +## Using Add this to your `Cargo.toml` @@ -24,14 +26,16 @@ simconnect = "0.4" _You must have SimConnect.dll in the same directory as your executable._ -### Building + +## Building _The SimConnect binaries are included within this repository, but they may not be up-to-date._ 1. Run `cargo build` 2. Add import `use simconnect` at the top of your file -### Examples + +## Examples Read float position data @@ -45,6 +49,7 @@ Requests tagged data with thresholds from SimConnect, and reads floats/strings cargo run --example aircraft_updates_on_change ``` -### Remarks + +## Remarks I have not tested every function of the API. If you find an error, feel free to make an issue or pull request. From cc1e481138b86936372f5f007b56018fb0aedbe7 Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Fri, 8 May 2026 01:00:54 -0400 Subject: [PATCH 5/7] Shorten about --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 24ee76b..70d97c7 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ # SimConnect Bindings for Rust -This crate provides Rust bindings to send/receive information through SimConnect, for Microsoft Flight Simulator (2020). +Send and receive information through SimConnect, for Microsoft Flight Simulator (2020). Documentation can be found at: [MSFS 2020 SDK](https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/SimConnect_SDK.htm) From b5874b70b600c28f0917b96d7473e9b69a360e01 Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Wed, 1 Jul 2026 12:39:15 -0400 Subject: [PATCH 6/7] Refactor and update for SU16 --- Cargo.lock | 34 +- Cargo.toml | 4 +- build.rs | 548 +++++++++++---------- src/lib.rs | 1361 ++++++++++++++++++++++++++-------------------------- 4 files changed, 983 insertions(+), 964 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ee65d1..d662df3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "cexpr" @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "glob" @@ -102,15 +102,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "minimal-lexical" @@ -149,18 +149,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustc-hash" @@ -199,16 +199,16 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simconnect" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bindgen", ] [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index a0b921b..8d08e3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,9 @@ name = "simconnect" license = "MIT" description = "Rust bindings for SimConnect" -version = "0.4.0" +version = "0.5.0" authors = ["Connor T"] -edition = "2018" +edition = "2021" [[example]] name = "aircraft_updates_on_change" diff --git a/build.rs b/build.rs index 5973c70..f65b5f4 100644 --- a/build.rs +++ b/build.rs @@ -4,267 +4,299 @@ fn main() { println!("cargo:rustc-link-search=libsrc/lib"); println!("cargo:rustc-link-lib=static=SimConnect"); - let bindings = bindgen::Builder::default() - .header("libsrc/include/SimConnect.hpp") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + let handle = std::thread::Builder::new() + .stack_size(128 * 1024 * 1024) + .spawn(|| { + let mut builder = bindgen::Builder::default() + .header("libsrc/include/SimConnect.hpp") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .impl_debug(true); - // ==================== CONSTANTS ==================== - .allowlist_var("SIMCONNECT_UNUSED") - .allowlist_var("SIMCONNECT_OBJECT_ID_USER") - .allowlist_var("SIMCONNECT_CAMERA_IGNORE_FIELD") - .allowlist_var("SIMCONNECT_CLIENTDATA_MAX_SIZE") - .allowlist_var("SIMCONNECT_GROUP_PRIORITY_HIGHEST") - .allowlist_var("SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE") - .allowlist_var("SIMCONNECT_GROUP_PRIORITY_STANDARD") - .allowlist_var("SIMCONNECT_GROUP_PRIORITY_DEFAULT") - .allowlist_var("SIMCONNECT_GROUP_PRIORITY_LOWEST") - .allowlist_var("MAX_METAR_LENGTH") - .allowlist_var("MAX_THERMAL_SIZE") - .allowlist_var("MAX_THERMAL_RATE") - .allowlist_var("INITPOSITION_AIRSPEED_CRUISE") - .allowlist_var("INITPOSITION_AIRSPEED_KEEP") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_INT8") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_INT16") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_INT32") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_INT64") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_FLOAT32") - .allowlist_var("SIMCONNECT_CLIENTDATATYPE_FLOAT64") - .allowlist_var("SIMCONNECT_CLIENTDATAOFFSET_AUTO") - .allowlist_var("SIMCONNECT_OPEN_CONFIGINDEX_LOCAL") - .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL") - .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER") - .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE") - .allowlist_var("SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME") - .allowlist_var("SIMCONNECT_WAYPOINT_NONE") - .allowlist_var("SIMCONNECT_WAYPOINT_SPEED_REQUESTED") - .allowlist_var("SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED") - .allowlist_var("SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED") - .allowlist_var("SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL") - .allowlist_var("SIMCONNECT_WAYPOINT_ON_GROUND") - .allowlist_var("SIMCONNECT_WAYPOINT_REVERSE") - .allowlist_var("SIMCONNECT_WAYPOINT_WRAP_TO_FIRST") - .allowlist_var("SIMCONNECT_WAYPOINT_ALWAYS_BACKUP") - .allowlist_var("SIMCONNECT_WAYPOINT_KEEP_LAST_HEADING") - .allowlist_var("SIMCONNECT_WAYPOINT_YIELD_TO_USER") - .allowlist_var("SIMCONNECT_WAYPOINT_CAN_REVERSE") - .allowlist_var("SIMCONNECT_EVENT_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER") - .allowlist_var("SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER") - .allowlist_var("SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY") - .allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_CHANGED") - .allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_TAGGED") - .allowlist_var("SIMCONNECT_DATA_SET_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_DATA_SET_FLAG_TAGGED") - .allowlist_var("SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY") - .allowlist_var("SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED") - .allowlist_var("SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED") - .allowlist_var("SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT") - .allowlist_var("SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED") - .allowlist_var("SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D") - .allowlist_var("SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL") - .allowlist_var("SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL") - .allowlist_var("SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER") - .allowlist_var("UNKNOWN_SENDID") - .allowlist_var("UNKNOWN_INDEX") - .allowlist_var("UNKNOWN_GROUP") - .allowlist_var("SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH") - .allowlist_var("SIMCONNECT_CLOUD_STATE_ARRAY_SIZE") - .allowlist_var("SIMCONNECT_PICK_GROUND") - .allowlist_var("SIMCONNECT_PICK_AI") - .allowlist_var("SIMCONNECT_PICK_SCENERY") - .allowlist_var("SIMCONNECT_PICK_ALL") - .allowlist_var("SIMCONNECT_PICK_COORDSASPIXELS") + // ==================== CONSTANTS / VARS ==================== + let vars = [ + "SIMCONNECT_UNUSED", + "SIMCONNECT_OBJECT_ID_USER", + "SIMCONNECT_CAMERA_IGNORE_FIELD", + "SIMCONNECT_CLIENTDATA_MAX_SIZE", + "SIMCONNECT_GROUP_PRIORITY_HIGHEST", + "SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE", + "SIMCONNECT_GROUP_PRIORITY_STANDARD", + "SIMCONNECT_GROUP_PRIORITY_DEFAULT", + "SIMCONNECT_GROUP_PRIORITY_LOWEST", + "MAX_METAR_LENGTH", + "MAX_THERMAL_SIZE", + "MAX_THERMAL_RATE", + "INITPOSITION_AIRSPEED_CRUISE", + "INITPOSITION_AIRSPEED_KEEP", + "SIMCONNECT_CLIENTDATATYPE_INT8", + "SIMCONNECT_CLIENTDATATYPE_INT16", + "SIMCONNECT_CLIENTDATATYPE_INT32", + "SIMCONNECT_CLIENTDATATYPE_INT64", + "SIMCONNECT_CLIENTDATATYPE_FLOAT32", + "SIMCONNECT_CLIENTDATATYPE_FLOAT64", + "SIMCONNECT_CLIENTDATAOFFSET_AUTO", + "SIMCONNECT_OPEN_CONFIGINDEX_LOCAL", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME", + "SIMCONNECT_WAYPOINT_NONE", + "SIMCONNECT_WAYPOINT_SPEED_REQUESTED", + "SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED", + "SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED", + "SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL", + "SIMCONNECT_WAYPOINT_ON_GROUND", + "SIMCONNECT_WAYPOINT_REVERSE", + "SIMCONNECT_WAYPOINT_WRAP_TO_FIRST", + "SIMCONNECT_WAYPOINT_ALWAYS_BACKUP", + "SIMCONNECT_WAYPOINT_KEEP_LAST_HEADING", + "SIMCONNECT_WAYPOINT_YIELD_TO_USER", + "SIMCONNECT_WAYPOINT_CAN_REVERSE", + "SIMCONNECT_EVENT_FLAG_DEFAULT", + "SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER", + "SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER", + "SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY", + "SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT", + "SIMCONNECT_DATA_REQUEST_FLAG_CHANGED", + "SIMCONNECT_DATA_REQUEST_FLAG_TAGGED", + "SIMCONNECT_DATA_SET_FLAG_DEFAULT", + "SIMCONNECT_DATA_SET_FLAG_TAGGED", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED", + "SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT", + "SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL", + "SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER", + "UNKNOWN_SENDID", + "UNKNOWN_INDEX", + "UNKNOWN_GROUP", + "SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH", + "SIMCONNECT_CLOUD_STATE_ARRAY_SIZE", + "SIMCONNECT_PICK_GROUND", + "SIMCONNECT_PICK_AI", + "SIMCONNECT_PICK_SCENERY", + "SIMCONNECT_PICK_ALL", + "SIMCONNECT_PICK_COORDSASPIXELS", + ]; - // ==================== TYPES / ENUMS ==================== - .allowlist_type("HANDLE") - .allowlist_type("SIMCONNECT_RECV_ID") - .allowlist_type("SIMCONNECT_DATATYPE") - .allowlist_type("SIMCONNECT_EXCEPTION") - .allowlist_type("SIMCONNECT_SIMOBJECT_TYPE") - .allowlist_type("SIMCONNECT_STATE") - .allowlist_type("SIMCONNECT_PERIOD") - .allowlist_type("SIMCONNECT_MISSION_END") - .allowlist_type("SIMCONNECT_CLIENT_DATA_PERIOD") - .allowlist_type("SIMCONNECT_TEXT_TYPE") - .allowlist_type("SIMCONNECT_TEXT_RESULT") - .allowlist_type("SIMCONNECT_WEATHER_MODE") - .allowlist_type("SIMCONNECT_FACILITY_LIST_TYPE") - .allowlist_type("SIMCONNECT_FACILITY_DATA_TYPE") - .allowlist_type("SIMCONNECT_INPUT_EVENT_TYPE") - .allowlist_type("SIMCONNECT_VOR_FLAGS") - .allowlist_type("SIMCONNECT_WAYPOINT_FLAGS") - .allowlist_type("SIMCONNECT_EVENT_FLAG") - .allowlist_type("SIMCONNECT_DATA_REQUEST_FLAG") - .allowlist_type("SIMCONNECT_DATA_SET_FLAG") - .allowlist_type("SIMCONNECT_CREATE_CLIENT_DATA_FLAG") - .allowlist_type("SIMCONNECT_CLIENT_DATA_REQUEST_FLAG") - .allowlist_type("SIMCONNECT_CLIENT_DATA_SET_FLAG") - .allowlist_type("SIMCONNECT_VIEW_SYSTEM_EVENT_DATA") - .allowlist_type("SIMCONNECT_SOUND_SYSTEM_EVENT_DATA") - .allowlist_type("SIMCONNECT_PICK_FLAGS") + for v in vars { + builder = builder.allowlist_var(v); + } - // ==================== STRUCTS ==================== - .allowlist_type("SIMCONNECT_RECV") - .allowlist_type("SIMCONNECT_RECV_EXCEPTION") - .allowlist_type("SIMCONNECT_RECV_OPEN") - .allowlist_type("SIMCONNECT_RECV_QUIT") - .allowlist_type("SIMCONNECT_RECV_EVENT") - .allowlist_type("SIMCONNECT_RECV_EVENT_FILENAME") - .allowlist_type("SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE") - .allowlist_type("SIMCONNECT_RECV_EVENT_FRAME") - .allowlist_type("SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED") - .allowlist_type("SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED") - .allowlist_type("SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED") - .allowlist_type("SIMCONNECT_RECV_EVENT_RACE_END") - .allowlist_type("SIMCONNECT_RECV_EVENT_RACE_LAP") - .allowlist_type("SIMCONNECT_RECV_SIMOBJECT_DATA") - .allowlist_type("SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE") - .allowlist_type("SIMCONNECT_RECV_CLIENT_DATA") - .allowlist_type("SIMCONNECT_RECV_WEATHER_OBSERVATION") - .allowlist_type("SIMCONNECT_RECV_CLOUD_STATE") - .allowlist_type("SIMCONNECT_RECV_ASSIGNED_OBJECT_ID") - .allowlist_type("SIMCONNECT_RECV_RESERVED_KEY") - .allowlist_type("SIMCONNECT_RECV_SYSTEM_STATE") - .allowlist_type("SIMCONNECT_RECV_CUSTOM_ACTION") - .allowlist_type("SIMCONNECT_RECV_EVENT_WEATHER_MODE") - .allowlist_type("SIMCONNECT_RECV_FACILITIES_LIST") - .allowlist_type("SIMCONNECT_DATA_FACILITY_AIRPORT") - .allowlist_type("SIMCONNECT_RECV_AIRPORT_LIST") - .allowlist_type("SIMCONNECT_DATA_FACILITY_WAYPOINT") - .allowlist_type("SIMCONNECT_RECV_WAYPOINT_LIST") - .allowlist_type("SIMCONNECT_DATA_FACILITY_NDB") - .allowlist_type("SIMCONNECT_RECV_NDB_LIST") - .allowlist_type("SIMCONNECT_DATA_FACILITY_VOR") - .allowlist_type("SIMCONNECT_RECV_VOR_LIST") - .allowlist_type("SIMCONNECT_RECV_PICK") - .allowlist_type("SIMCONNECT_RECV_EVENT_EX1") - .allowlist_type("SIMCONNECT_DATA_RACE_RESULT") - .allowlist_type("SIMCONNECT_RECV_FACILITY_DATA") - .allowlist_type("SIMCONNECT_RECV_FACILITY_DATA_END") - .allowlist_type("SIMCONNECT_ICAO") - .allowlist_type("SIMCONNECT_FACILITY_MINIMAL") - .allowlist_type("SIMCONNECT_RECV_FACILITY_MINIMAL_LIST") - .allowlist_type("SIMCONNECT_DATA_PBH") - .allowlist_type("SIMCONNECT_JETWAY_DATA") - .allowlist_type("SIMCONNECT_RECV_JETWAY_DATA") - .allowlist_type("SIMCONNECT_RECV_ACTION_CALLBACK") - .allowlist_type("SIMCONNECT_INPUT_EVENT_DESCRIPTOR") - .allowlist_type("SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS") - .allowlist_type("SIMCONNECT_RECV_GET_INPUT_EVENT") - .allowlist_type("SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT") - .allowlist_type("SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS") - .allowlist_type("SIMCONNECT_VERSION_BASE_TYPE") - .allowlist_type("SIMCONNECT_CONTROLLER_ITEM") - .allowlist_type("SIMCONNECT_RECV_CONTROLLERS_LIST") - .allowlist_type("SIMCONNECT_RECV_LIST_TEMPLATE") - .allowlist_type("SIMCONNECT_DATA_INITPOSITION") - .allowlist_type("SIMCONNECT_DATA_MARKERSTATE") - .allowlist_type("SIMCONNECT_DATA_WAYPOINT") - .allowlist_type("SIMCONNECT_DATA_LATLONALT") - .allowlist_type("SIMCONNECT_DATA_XYZ") + // ==================== TYPES / ENUMS ==================== + let types = [ + "HANDLE", + "SIMCONNECT_RECV_ID", + "SIMCONNECT_DATATYPE", + "SIMCONNECT_EXCEPTION", + "SIMCONNECT_SIMOBJECT_TYPE", + "SIMCONNECT_STATE", + "SIMCONNECT_PERIOD", + "SIMCONNECT_MISSION_END", + "SIMCONNECT_CLIENT_DATA_PERIOD", + "SIMCONNECT_TEXT_TYPE", + "SIMCONNECT_TEXT_RESULT", + "SIMCONNECT_WEATHER_MODE", + "SIMCONNECT_FACILITY_LIST_TYPE", + "SIMCONNECT_FACILITY_DATA_TYPE", + "SIMCONNECT_INPUT_EVENT_TYPE", + "SIMCONNECT_VOR_FLAGS", + "SIMCONNECT_WAYPOINT_FLAGS", + "SIMCONNECT_EVENT_FLAG", + "SIMCONNECT_DATA_REQUEST_FLAG", + "SIMCONNECT_DATA_SET_FLAG", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG", + "SIMCONNECT_CLIENT_DATA_SET_FLAG", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA", + "SIMCONNECT_SOUND_SYSTEM_EVENT_DATA", + "SIMCONNECT_PICK_FLAGS", + ]; - // ==================== FUNCTIONS ==================== - .allowlist_function("SimConnect_MapClientEventToSimEvent") - .allowlist_function("SimConnect_TransmitClientEvent") - .allowlist_function("SimConnect_SetSystemEventState") - .allowlist_function("SimConnect_AddClientEventToNotificationGroup") - .allowlist_function("SimConnect_RemoveClientEvent") - .allowlist_function("SimConnect_SetNotificationGroupPriority") - .allowlist_function("SimConnect_ClearNotificationGroup") - .allowlist_function("SimConnect_RequestNotificationGroup") - .allowlist_function("SimConnect_AddToDataDefinition") - .allowlist_function("SimConnect_ClearDataDefinition") - .allowlist_function("SimConnect_RequestDataOnSimObject") - .allowlist_function("SimConnect_RequestDataOnSimObjectType") - .allowlist_function("SimConnect_SetDataOnSimObject") - .allowlist_function("SimConnect_MapInputEventToClientEvent") - .allowlist_function("SimConnect_SetInputGroupPriority") - .allowlist_function("SimConnect_RemoveInputEvent") - .allowlist_function("SimConnect_ClearInputGroup") - .allowlist_function("SimConnect_SetInputGroupState") - .allowlist_function("SimConnect_RequestReservedKey") - .allowlist_function("SimConnect_SubscribeToSystemEvent") - .allowlist_function("SimConnect_UnsubscribeFromSystemEvent") - .allowlist_function("SimConnect_WeatherRequestInterpolatedObservation") - .allowlist_function("SimConnect_WeatherRequestObservationAtStation") - .allowlist_function("SimConnect_WeatherRequestObservationAtNearestStation") - .allowlist_function("SimConnect_WeatherCreateStation") - .allowlist_function("SimConnect_WeatherRemoveStation") - .allowlist_function("SimConnect_WeatherSetObservation") - .allowlist_function("SimConnect_WeatherSetModeServer") - .allowlist_function("SimConnect_WeatherSetModeTheme") - .allowlist_function("SimConnect_WeatherSetModeGlobal") - .allowlist_function("SimConnect_WeatherSetModeCustom") - .allowlist_function("SimConnect_WeatherSetDynamicUpdateRate") - .allowlist_function("SimConnect_WeatherRequestCloudState") - .allowlist_function("SimConnect_WeatherCreateThermal") - .allowlist_function("SimConnect_WeatherRemoveThermal") - .allowlist_function("SimConnect_AICreateParkedATCAircraft") - .allowlist_function("SimConnect_AICreateEnrouteATCAircraft") - .allowlist_function("SimConnect_AICreateNonATCAircraft") - .allowlist_function("SimConnect_AICreateSimulatedObject") - .allowlist_function("SimConnect_AIReleaseControl") - .allowlist_function("SimConnect_AIRemoveObject") - .allowlist_function("SimConnect_AISetAircraftFlightPlan") - .allowlist_function("SimConnect_ExecuteMissionAction") - .allowlist_function("SimConnect_CompleteCustomMissionAction") - .allowlist_function("SimConnect_Close") - .allowlist_function("SimConnect_RetrieveString") - .allowlist_function("SimConnect_GetLastSentPacketID") - .allowlist_function("SimConnect_Open") - .allowlist_function("SimConnect_CallDispatch") - .allowlist_function("SimConnect_GetNextDispatch") - .allowlist_function("SimConnect_RequestResponseTimes") - .allowlist_function("SimConnect_InsertString") - .allowlist_function("SimConnect_CameraSetRelative6DOF") - .allowlist_function("SimConnect_MenuAddItem") - .allowlist_function("SimConnect_MenuDeleteItem") - .allowlist_function("SimConnect_MenuAddSubItem") - .allowlist_function("SimConnect_MenuDeleteSubItem") - .allowlist_function("SimConnect_RequestSystemState") - .allowlist_function("SimConnect_SetSystemState") - .allowlist_function("SimConnect_MapClientDataNameToID") - .allowlist_function("SimConnect_CreateClientData") - .allowlist_function("SimConnect_AddToClientDataDefinition") - .allowlist_function("SimConnect_ClearClientDataDefinition") - .allowlist_function("SimConnect_RequestClientData") - .allowlist_function("SimConnect_SetClientData") - .allowlist_function("SimConnect_FlightLoad") - .allowlist_function("SimConnect_FlightSave") - .allowlist_function("SimConnect_FlightPlanLoad") - .allowlist_function("SimConnect_Text") - .allowlist_function("SimConnect_SubscribeToFacilities") - .allowlist_function("SimConnect_UnsubscribeToFacilities") - .allowlist_function("SimConnect_RequestFacilitiesList") - .allowlist_function("SimConnect_TransmitClientEvent_EX1") - .allowlist_function("SimConnect_AddToFacilityDefinition") - .allowlist_function("SimConnect_RequestFacilityData") - .allowlist_function("SimConnect_SubscribeToFacilities_EX1") - .allowlist_function("SimConnect_UnsubscribeToFacilities_EX1") - .allowlist_function("SimConnect_RequestFacilitiesList_EX1") - .allowlist_function("SimConnect_RequestFacilityData_EX1") - .allowlist_function("SimConnect_RequestJetwayData") - .allowlist_function("SimConnect_EnumerateControllers") - .allowlist_function("SimConnect_MapInputEventToClientEvent_EX1") - .allowlist_function("SimConnect_ExecuteAction") - .allowlist_function("SimConnect_EnumerateInputEvents") - .allowlist_function("SimConnect_GetInputEvent") - .allowlist_function("SimConnect_SetInputEvent") - .allowlist_function("SimConnect_SubscribeInputEvent") - .allowlist_function("SimConnect_UnsubscribeInputEvent") - .allowlist_function("SimConnect_EnumerateInputEventParams") - .allowlist_function("SimConnect_AddFacilityDataDefinitionFilter") - .allowlist_function("SimConnect_ClearAllFacilityDataDefinitionFilters") + for t in types { + builder = builder.allowlist_type(t); + } - .impl_debug(true) - .generate() - .expect("Unable to generate bindings"); + // ==================== STRUCTS ==================== + let structs = [ + "SIMCONNECT_RECV", + "SIMCONNECT_RECV_EXCEPTION", + "SIMCONNECT_RECV_OPEN", + "SIMCONNECT_RECV_QUIT", + "SIMCONNECT_RECV_EVENT", + "SIMCONNECT_RECV_EVENT_FILENAME", + "SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE", + "SIMCONNECT_RECV_EVENT_FRAME", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED", + "SIMCONNECT_RECV_EVENT_RACE_END", + "SIMCONNECT_RECV_EVENT_RACE_LAP", + "SIMCONNECT_RECV_SIMOBJECT_DATA", + "SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE", + "SIMCONNECT_RECV_CLIENT_DATA", + "SIMCONNECT_RECV_WEATHER_OBSERVATION", + "SIMCONNECT_RECV_CLOUD_STATE", + "SIMCONNECT_RECV_ASSIGNED_OBJECT_ID", + "SIMCONNECT_RECV_RESERVED_KEY", + "SIMCONNECT_RECV_SYSTEM_STATE", + "SIMCONNECT_RECV_CUSTOM_ACTION", + "SIMCONNECT_RECV_EVENT_WEATHER_MODE", + "SIMCONNECT_RECV_FACILITIES_LIST", + "SIMCONNECT_DATA_FACILITY_AIRPORT", + "SIMCONNECT_RECV_AIRPORT_LIST", + "SIMCONNECT_DATA_FACILITY_WAYPOINT", + "SIMCONNECT_RECV_WAYPOINT_LIST", + "SIMCONNECT_DATA_FACILITY_NDB", + "SIMCONNECT_RECV_NDB_LIST", + "SIMCONNECT_DATA_FACILITY_VOR", + "SIMCONNECT_RECV_VOR_LIST", + "SIMCONNECT_RECV_EVENT_EX1", + "SIMCONNECT_DATA_RACE_RESULT", + "SIMCONNECT_RECV_FACILITY_DATA", + "SIMCONNECT_RECV_FACILITY_DATA_END", + "SIMCONNECT_ICAO", + "SIMCONNECT_FACILITY_MINIMAL", + "SIMCONNECT_RECV_FACILITY_MINIMAL_LIST", + "SIMCONNECT_DATA_PBH", + "SIMCONNECT_JETWAY_DATA", + "SIMCONNECT_RECV_JETWAY_DATA", + "SIMCONNECT_RECV_ACTION_CALLBACK", + "SIMCONNECT_INPUT_EVENT_DESCRIPTOR", + "SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS", + "SIMCONNECT_RECV_GET_INPUT_EVENT", + "SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT", + "SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS", + "SIMCONNECT_VERSION_BASE_TYPE", + "SIMCONNECT_CONTROLLER_ITEM", + "SIMCONNECT_RECV_CONTROLLERS_LIST", + "SIMCONNECT_RECV_LIST_TEMPLATE", + "SIMCONNECT_DATA_INITPOSITION", + "SIMCONNECT_DATA_MARKERSTATE", + "SIMCONNECT_DATA_WAYPOINT", + "SIMCONNECT_DATA_LATLONALT", + "SIMCONNECT_DATA_XYZ", + "SIMCONNECT_RECV_PICK", + ]; - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); -} + for s in structs { + builder = builder.allowlist_type(s); + } + + // ==================== FUNCTIONS ==================== + let functions = [ + "SimConnect_MapClientEventToSimEvent", + "SimConnect_TransmitClientEvent", + "SimConnect_SetSystemEventState", + "SimConnect_AddClientEventToNotificationGroup", + "SimConnect_RemoveClientEvent", + "SimConnect_SetNotificationGroupPriority", + "SimConnect_ClearNotificationGroup", + "SimConnect_RequestNotificationGroup", + "SimConnect_AddToDataDefinition", + "SimConnect_ClearDataDefinition", + "SimConnect_RequestDataOnSimObject", + "SimConnect_RequestDataOnSimObjectType", + "SimConnect_SetDataOnSimObject", + "SimConnect_MapInputEventToClientEvent", + "SimConnect_SetInputGroupPriority", + "SimConnect_RemoveInputEvent", + "SimConnect_ClearInputGroup", + "SimConnect_SetInputGroupState", + "SimConnect_RequestReservedKey", + "SimConnect_SubscribeToSystemEvent", + "SimConnect_UnsubscribeFromSystemEvent", + "SimConnect_WeatherRequestInterpolatedObservation", + "SimConnect_WeatherRequestObservationAtStation", + "SimConnect_WeatherRequestObservationAtNearestStation", + "SimConnect_WeatherCreateStation", + "SimConnect_WeatherRemoveStation", + "SimConnect_WeatherSetObservation", + "SimConnect_WeatherSetModeServer", + "SimConnect_WeatherSetModeTheme", + "SimConnect_WeatherSetModeGlobal", + "SimConnect_WeatherSetModeCustom", + "SimConnect_WeatherSetDynamicUpdateRate", + "SimConnect_WeatherRequestCloudState", + "SimConnect_WeatherCreateThermal", + "SimConnect_WeatherRemoveThermal", + "SimConnect_AICreateParkedATCAircraft", + "SimConnect_AICreateEnrouteATCAircraft", + "SimConnect_AICreateNonATCAircraft", + "SimConnect_AICreateSimulatedObject", + "SimConnect_AIReleaseControl", + "SimConnect_AIRemoveObject", + "SimConnect_AISetAircraftFlightPlan", + "SimConnect_ExecuteMissionAction", + "SimConnect_CompleteCustomMissionAction", + "SimConnect_Close", + "SimConnect_RetrieveString", + "SimConnect_GetLastSentPacketID", + "SimConnect_Open", + "SimConnect_CallDispatch", + "SimConnect_GetNextDispatch", + "SimConnect_RequestResponseTimes", + "SimConnect_InsertString", + "SimConnect_CameraSetRelative6DOF", + "SimConnect_MenuAddItem", + "SimConnect_MenuDeleteItem", + "SimConnect_MenuAddSubItem", + "SimConnect_MenuDeleteSubItem", + "SimConnect_RequestSystemState", + "SimConnect_SetSystemState", + "SimConnect_MapClientDataNameToID", + "SimConnect_CreateClientData", + "SimConnect_AddToClientDataDefinition", + "SimConnect_ClearClientDataDefinition", + "SimConnect_RequestClientData", + "SimConnect_SetClientData", + "SimConnect_FlightLoad", + "SimConnect_FlightSave", + "SimConnect_FlightPlanLoad", + "SimConnect_Text", + "SimConnect_SubscribeToFacilities", + "SimConnect_UnsubscribeToFacilities", + "SimConnect_RequestFacilitiesList", + "SimConnect_TransmitClientEvent_EX1", + "SimConnect_AddToFacilityDefinition", + "SimConnect_RequestFacilityData", + "SimConnect_SubscribeToFacilities_EX1", + "SimConnect_UnsubscribeToFacilities_EX1", + "SimConnect_RequestFacilitiesList_EX1", + "SimConnect_RequestFacilityData_EX1", + "SimConnect_RequestJetwayData", + "SimConnect_EnumerateControllers", + "SimConnect_MapInputEventToClientEvent_EX1", + "SimConnect_ExecuteAction", + "SimConnect_EnumerateInputEvents", + "SimConnect_GetInputEvent", + "SimConnect_SetInputEvent", + "SimConnect_SubscribeInputEvent", + "SimConnect_UnsubscribeInputEvent", + "SimConnect_EnumerateInputEventParams", + "SimConnect_AddFacilityDataDefinitionFilter", + "SimConnect_ClearAllFacilityDataDefinitionFilters", + ]; + + for f in functions { + builder = builder.allowlist_function(f); + } + + let bindings = builder + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); + }) + .expect("Failed to spawn bindgen thread"); + + handle.join().expect("Bindgen thread panicked"); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9a47fe7..1cc9599 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,10 @@ #![allow(non_snake_case)] use std::ffi::CString; -use std::mem::transmute_copy; use std::ptr; include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -/// Enumerations for all the possible data types received from SimConnect #[derive(Debug)] pub enum DispatchResult<'a> { Null, @@ -52,17 +50,14 @@ pub enum DispatchResult<'a> { ControllersList(&'a SIMCONNECT_RECV_CONTROLLERS_LIST), } -/// Handles communication between the client program and SimConnect #[derive(Debug)] pub struct SimConnector { - sim_connect_handle: HANDLE, + handle: HANDLE, } impl Default for SimConnector { fn default() -> Self { - Self { - sim_connect_handle: std::ptr::null_mut(), - } + Self { handle: ptr::null_mut() } } } @@ -71,44 +66,52 @@ impl SimConnector { Self::default() } - pub fn connect(&mut self, program_name: &str) -> bool { - unsafe { - let temp_1 = ptr::null_mut(); - let temp_2 = ptr::null_mut(); + // ==================== Connection & Lifecycle ==================== - let program_name = CString::new(program_name).unwrap(); + pub fn connect(&mut self, program_name: &str) -> bool { + let name = cstring(program_name); + unsafe { SimConnect_Open( - &mut self.sim_connect_handle, - program_name.as_ptr(), - temp_1, + &mut self.handle, + name.as_ptr(), + ptr::null_mut(), 0, - temp_2, + ptr::null_mut(), 0, - ); + ) == 0 + } + } - !self.sim_connect_handle.is_null() + pub fn close(&mut self) -> bool { + if self.handle.is_null() { + return true; } + let result = unsafe { SimConnect_Close(self.handle) == 0 }; + self.handle = ptr::null_mut(); + result } + // ==================== Data Definition ==================== + pub fn add_data_definition( &self, define_id: SIMCONNECT_DATA_DEFINITION_ID, datum_name: &str, units_name: &str, datum_type: SIMCONNECT_DATATYPE, - datum_id: DWORD, epsilon: f32, + datum_id: DWORD, ) -> bool { - let datum_name = CString::new(datum_name).unwrap(); - let units_name = CString::new(units_name).unwrap(); + let name = cstring(datum_name); + let units = cstring(units_name); unsafe { SimConnect_AddToDataDefinition( - self.sim_connect_handle, + self.handle, define_id, - datum_name.as_ptr(), - units_name.as_ptr(), + name.as_ptr(), + units.as_ptr(), datum_type, epsilon, datum_id, @@ -116,327 +119,309 @@ impl SimConnector { } } - pub fn set_system_event_state( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - state: SIMCONNECT_STATE, - ) -> bool { - unsafe { SimConnect_SetSystemEventState(self.sim_connect_handle, event_id, state) == 0 } + pub fn clear_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { + unsafe { SimConnect_ClearDataDefinition(self.handle, define_id) == 0 } } - pub fn remove_client_event( + // ==================== Events ==================== + + pub fn map_client_event_to_sim_event( &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, ) -> bool { - unsafe { SimConnect_RemoveClientEvent(self.sim_connect_handle, group_id, event_id) == 0 } - } - - pub fn clear_notification_group(&self, group_id: SIMCONNECT_NOTIFICATION_GROUP_ID) -> bool { - unsafe { SimConnect_ClearNotificationGroup(self.sim_connect_handle, group_id) == 0 } + let name = cstring(event_name); + unsafe { SimConnect_MapClientEventToSimEvent(self.handle, event_id, name.as_ptr()) == 0 } } - pub fn request_notification_group( + pub fn subscribe_to_system_event( &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - reserved: DWORD, - flags: DWORD, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, ) -> bool { + let name = cstring(event_name); unsafe { - SimConnect_RequestNotificationGroup(self.sim_connect_handle, group_id, reserved, flags) - == 0 + SimConnect_SubscribeToSystemEvent(self.handle, event_id, name.as_ptr()) == 0 } } - pub fn clear_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { - unsafe { SimConnect_ClearDataDefinition(self.sim_connect_handle, define_id) == 0 } + pub fn unsubscribe_from_system_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_UnsubscribeFromSystemEvent(self.handle, event_id) == 0 } } - pub fn create_client_data( + pub fn set_system_event_state( &self, - data_id: SIMCONNECT_CLIENT_DATA_ID, - size: DWORD, - flags: SIMCONNECT_CREATE_CLIENT_DATA_FLAG, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + state: SIMCONNECT_STATE, ) -> bool { - unsafe { SimConnect_CreateClientData(self.sim_connect_handle, data_id, size, flags) == 0 } + unsafe { SimConnect_SetSystemEventState(self.handle, event_id, state) == 0 } } - pub fn request_data_on_sim_object_type( + pub fn transmit_client_event( &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - radius_in_meters: DWORD, - object_type: SIMCONNECT_SIMOBJECT_TYPE, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + dw_data: DWORD, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, ) -> bool { unsafe { - SimConnect_RequestDataOnSimObjectType( - self.sim_connect_handle, - request_id, - define_id, - radius_in_meters, - object_type, + SimConnect_TransmitClientEvent( + self.handle, + object_id, + event_id, + dw_data, + group_id, + flags, ) == 0 } } - pub fn remove_input_event( + pub fn add_client_event_to_notification_group( &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + maskable: bool, ) -> bool { - let input_definition = CString::new(input_definition).unwrap(); - unsafe { - SimConnect_RemoveInputEvent( - self.sim_connect_handle, + SimConnect_AddClientEventToNotificationGroup( + self.handle, group_id, - input_definition.as_ptr(), + event_id, + maskable as i32, ) == 0 } } - pub fn clear_input_group(&self, group_id: SIMCONNECT_INPUT_GROUP_ID) -> bool { - unsafe { SimConnect_ClearInputGroup(self.sim_connect_handle, group_id) == 0 } - } - - pub fn request_reserved_key( + pub fn set_notification_group_priority( &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - key_choice_1: &str, - key_choice_2: &str, - key_choice_3: &str, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + priority: DWORD, ) -> bool { - let key_choice_1 = CString::new(key_choice_1).unwrap(); - let key_choice_2 = CString::new(key_choice_2).unwrap(); - let key_choice_3 = CString::new(key_choice_3).unwrap(); - unsafe { - SimConnect_RequestReservedKey( - self.sim_connect_handle, - event_id, - key_choice_1.as_ptr(), - key_choice_2.as_ptr(), - key_choice_3.as_ptr(), - ) == 0 + SimConnect_SetNotificationGroupPriority(self.handle, group_id, priority) == 0 } } - pub fn unsubscribe_from_system_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { - unsafe { SimConnect_UnsubscribeFromSystemEvent(self.sim_connect_handle, event_id) == 0 } - } - - pub fn ai_create_parked_atc_aircraft( + pub fn remove_client_event( &self, - container_title: &str, - tail_number: &str, - airport_id: &str, - request_id: SIMCONNECT_DATA_REQUEST_ID, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, ) -> bool { - let container_title = CString::new(container_title).unwrap(); - let tail_number = CString::new(tail_number).unwrap(); - let airport_id = CString::new(airport_id).unwrap(); + unsafe { SimConnect_RemoveClientEvent(self.handle, group_id, event_id) == 0 } + } - unsafe { - SimConnect_AICreateParkedATCAircraft( - self.sim_connect_handle, - container_title.as_ptr(), - tail_number.as_ptr(), - airport_id.as_ptr(), - request_id, - ) == 0 - } + pub fn clear_notification_group(&self, group_id: SIMCONNECT_NOTIFICATION_GROUP_ID) -> bool { + unsafe { SimConnect_ClearNotificationGroup(self.handle, group_id) == 0 } } - pub fn ai_create_enroute_atc_aircraft( + pub fn request_notification_group( &self, - container_title: &str, - tail_number: &str, - flight_number: i32, - flight_plan_path: &str, - flight_plan_position: f64, - touch_and_go: bool, - request_id: SIMCONNECT_DATA_REQUEST_ID, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + reserved: DWORD, + flags: DWORD, ) -> bool { - let container_title = CString::new(container_title).unwrap(); - let tail_number = CString::new(tail_number).unwrap(); - let flight_plan_path = CString::new(flight_plan_path).unwrap(); - unsafe { - SimConnect_AICreateEnrouteATCAircraft( - self.sim_connect_handle, - container_title.as_ptr(), - tail_number.as_ptr(), - flight_number, - flight_plan_path.as_ptr(), - flight_plan_position, - touch_and_go as i32, - request_id, - ) == 0 + SimConnect_RequestNotificationGroup(self.handle, group_id, reserved, flags) == 0 } } - pub fn ai_create_non_atc_aircraft( + pub fn transmit_client_event_ex1( &self, - container_title: &str, - tail_number: &str, - init_pos: SIMCONNECT_DATA_INITPOSITION, - request_id: SIMCONNECT_DATA_REQUEST_ID, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, + data0: DWORD, + data1: DWORD, + data2: DWORD, + data3: DWORD, + data4: DWORD, ) -> bool { - let container_title = CString::new(container_title).unwrap(); - let tail_number = CString::new(tail_number).unwrap(); - unsafe { - SimConnect_AICreateNonATCAircraft( - self.sim_connect_handle, - container_title.as_ptr(), - tail_number.as_ptr(), - init_pos, - request_id, + SimConnect_TransmitClientEvent_EX1( + self.handle, + object_id, + event_id, + group_id, + flags, + data0, + data1, + data2, + data3, + data4, ) == 0 } } - pub fn ai_create_simulated_object( + pub fn request_reserved_key( &self, - container_title: &str, - init_pos: SIMCONNECT_DATA_INITPOSITION, - request_id: SIMCONNECT_DATA_REQUEST_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + key_choice1: &str, + key_choice2: &str, + key_choice3: &str, ) -> bool { - let container_title = CString::new(container_title).unwrap(); + let k1 = cstring(key_choice1); + let k2 = cstring(key_choice2); + let k3 = cstring(key_choice3); unsafe { - SimConnect_AICreateSimulatedObject( - self.sim_connect_handle, - container_title.as_ptr(), - init_pos, - request_id, + SimConnect_RequestReservedKey( + self.handle, + event_id, + k1.as_ptr(), + k2.as_ptr(), + k3.as_ptr(), ) == 0 } } - pub fn ai_release_control( - &self, - object_id: SIMCONNECT_OBJECT_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { SimConnect_AIReleaseControl(self.sim_connect_handle, object_id, request_id) == 0 } - } + // ==================== Input Events ==================== - pub fn ai_remove_object( + pub fn map_input_event_to_client_event( &self, - object_id: SIMCONNECT_OBJECT_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, ) -> bool { - unsafe { SimConnect_AIRemoveObject(self.sim_connect_handle, object_id, request_id) == 0 } + let input = cstring(input_definition); + unsafe { + SimConnect_MapInputEventToClientEvent( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, + ) == 0 + } } - pub fn ai_set_aircraft_flight_plan( + pub fn map_input_event_to_client_event_ex1( &self, - object_id: SIMCONNECT_OBJECT_ID, - flight_plan_path: &str, - request_id: SIMCONNECT_DATA_REQUEST_ID, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, ) -> bool { - let flight_plan_path = CString::new(flight_plan_path).unwrap(); - + let input = cstring(input_definition); unsafe { - SimConnect_AISetAircraftFlightPlan( - self.sim_connect_handle, - object_id, - flight_plan_path.as_ptr(), - request_id, + SimConnect_MapInputEventToClientEvent_EX1( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, ) == 0 } } - pub fn execute_mission_action(&self, instance_id: GUID) -> bool { - unsafe { SimConnect_ExecuteMissionAction(self.sim_connect_handle, instance_id) == 0 } - } - - pub fn complete_custom_mission_action(&self, instance_id: GUID) -> bool { - unsafe { SimConnect_CompleteCustomMissionAction(self.sim_connect_handle, instance_id) == 0 } - } - - pub fn close(&self) -> bool { - unsafe { SimConnect_Close(self.sim_connect_handle) == 0 } + pub fn set_input_group_state(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, state: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupState(self.handle, group_id, state) == 0 } } - pub unsafe fn get_last_sent_packet_id(&self, error: *mut DWORD) -> bool { - unsafe { SimConnect_GetLastSentPacketID(self.sim_connect_handle, error) == 0 } + pub fn set_input_priority(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, priority: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupPriority(self.handle, group_id, priority) == 0 } } - pub unsafe fn call_dispatch( + pub fn remove_input_event( &self, - dispatch_callback: DispatchProc, - context: *mut std::os::raw::c_void, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, ) -> bool { - unsafe { SimConnect_CallDispatch(self.sim_connect_handle, dispatch_callback, context) == 0 } - } - - pub unsafe fn request_response_times(&self, count: DWORD, elapsed_seconds: *mut f32) -> bool { + let input = cstring(input_definition); unsafe { - SimConnect_RequestResponseTimes(self.sim_connect_handle, count, elapsed_seconds) == 0 + SimConnect_RemoveInputEvent(self.handle, group_id, input.as_ptr()) == 0 } } - pub fn camera_set_relative_6dof( + pub fn clear_input_group(&self, group_id: SIMCONNECT_INPUT_GROUP_ID) -> bool { + unsafe { SimConnect_ClearInputGroup(self.handle, group_id) == 0 } + } + + // ==================== Data Requests ==================== + + pub fn request_data_on_sim_object( &self, - delta_x: f32, - delta_y: f32, - delta_z: f32, - pitch: f32, - bank: f32, - heading: f32, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + period: SIMCONNECT_PERIOD, + flags: SIMCONNECT_DATA_REQUEST_FLAG, + origin: DWORD, + interval: DWORD, + limit: DWORD, ) -> bool { unsafe { - SimConnect_CameraSetRelative6DOF( - self.sim_connect_handle, - delta_x, - delta_y, - delta_z, - pitch, - bank, - heading, + SimConnect_RequestDataOnSimObject( + self.handle, + request_id, + define_id, + object_id, + period, + flags, + origin, + interval, + limit, ) == 0 } } - pub fn menu_add_item( + pub fn request_data_on_sim_object_type( &self, - menu_item: &str, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - data: DWORD, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + radius_in_meters: DWORD, + object_type: SIMCONNECT_SIMOBJECT_TYPE, ) -> bool { - let menu_item = CString::new(menu_item).unwrap(); - unsafe { - SimConnect_MenuAddItem(self.sim_connect_handle, menu_item.as_ptr(), event_id, data) == 0 + SimConnect_RequestDataOnSimObjectType( + self.handle, + request_id, + define_id, + radius_in_meters, + object_type, + ) == 0 } } - pub fn menu_delete_item(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { - unsafe { SimConnect_MenuDeleteItem(self.sim_connect_handle, event_id) == 0 } - } - - pub fn menu_delete_sub_item( + pub unsafe fn set_data_on_sim_object( &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - sub_event_id: SIMCONNECT_CLIENT_EVENT_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + flags: SIMCONNECT_DATA_SET_FLAG, + array_count: DWORD, + size: DWORD, + pntr: *mut std::os::raw::c_void, ) -> bool { unsafe { - SimConnect_MenuDeleteSubItem(self.sim_connect_handle, event_id, sub_event_id) == 0 + SimConnect_SetDataOnSimObject( + self.handle, define_id, object_id, flags, array_count, size, pntr, + ) == 0 } } - pub fn request_system_state( + // ==================== Client Data ==================== + + pub fn create_client_data( &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - state: &str, + data_id: SIMCONNECT_CLIENT_DATA_ID, + size: DWORD, + flags: SIMCONNECT_CREATE_CLIENT_DATA_FLAG, ) -> bool { - let state = CString::new(state).unwrap(); - - unsafe { - SimConnect_RequestSystemState(self.sim_connect_handle, request_id, state.as_ptr()) == 0 - } + unsafe { SimConnect_CreateClientData(self.handle, data_id, size, flags) == 0 } } pub fn map_client_data_name_to_id( @@ -444,14 +429,9 @@ impl SimConnector { client_data_name: &str, data_id: SIMCONNECT_CLIENT_DATA_ID, ) -> bool { - let client_data_name = CString::new(client_data_name).unwrap(); - + let name = cstring(client_data_name); unsafe { - SimConnect_MapClientDataNameToID( - self.sim_connect_handle, - client_data_name.as_ptr(), - data_id, - ) == 0 + SimConnect_MapClientDataNameToID(self.handle, name.as_ptr(), data_id) == 0 } } @@ -465,18 +445,13 @@ impl SimConnector { ) -> bool { unsafe { SimConnect_AddToClientDataDefinition( - self.sim_connect_handle, - define_id, - offset, - size_or_type, - epsilon, - datum_id, + self.handle, define_id, offset, size_or_type, epsilon, datum_id, ) == 0 } } pub fn clear_client_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { - unsafe { SimConnect_ClearClientDataDefinition(self.sim_connect_handle, define_id) == 0 } + unsafe { SimConnect_ClearClientDataDefinition(self.handle, define_id) == 0 } } pub fn request_client_data( @@ -492,7 +467,7 @@ impl SimConnector { ) -> bool { unsafe { SimConnect_RequestClientData( - self.sim_connect_handle, + self.handle, data_id, request_id, define_id, @@ -516,273 +491,352 @@ impl SimConnector { ) -> bool { unsafe { SimConnect_SetClientData( - self.sim_connect_handle, - data_id, - define_id, - flags, - reserved, - unit_size, - data_set, + self.handle, data_id, define_id, flags, reserved, unit_size, data_set, ) == 0 } } - pub fn flight_load(&self, file_name: &str) -> bool { - let file_name = CString::new(file_name).unwrap(); + // ==================== AI Objects ==================== - unsafe { SimConnect_FlightLoad(self.sim_connect_handle, file_name.as_ptr()) == 0 } - } - - pub unsafe fn text( + pub fn ai_create_parked_atc_aircraft( &self, - text_type: SIMCONNECT_TEXT_TYPE, - time_in_seconds: f32, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - unit_size: DWORD, - data_set: *mut std::os::raw::c_void, + container_title: &str, + tail_number: &str, + airport_id: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let airport = cstring(airport_id); + unsafe { - SimConnect_Text( - self.sim_connect_handle, - text_type, - time_in_seconds, - event_id, - unit_size, - data_set, + SimConnect_AICreateParkedATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + airport.as_ptr(), + request_id, ) == 0 } } - pub fn subscribe_to_facilities( + pub fn ai_create_enroute_atc_aircraft( &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, + container_title: &str, + tail_number: &str, + flight_number: i32, + flight_plan_path: &str, + flight_plan_position: f64, + touch_and_go: bool, request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let plan = cstring(flight_plan_path); + unsafe { - SimConnect_SubscribeToFacilities(self.sim_connect_handle, list_type, request_id) == 0 + SimConnect_AICreateEnrouteATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + flight_number, + plan.as_ptr(), + flight_plan_position, + touch_and_go as i32, + request_id, + ) == 0 } } - pub fn unsubscribe_to_facilities(&self, list_type: SIMCONNECT_FACILITY_LIST_TYPE) -> bool { - unsafe { SimConnect_UnsubscribeToFacilities(self.sim_connect_handle, list_type) == 0 } - } - - pub fn request_facilities_list( + pub fn ai_create_non_atc_aircraft( &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, + container_title: &str, + tail_number: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + unsafe { - SimConnect_RequestFacilitiesList(self.sim_connect_handle, list_type, request_id) == 0 + SimConnect_AICreateNonATCAircraft( + self.handle, title.as_ptr(), tail.as_ptr(), init_pos, request_id, + ) == 0 } } - pub fn request_data_on_sim_object( + pub fn ai_create_simulated_object( &self, + container_title: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, request_id: SIMCONNECT_DATA_REQUEST_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - object_id: SIMCONNECT_OBJECT_ID, - period: SIMCONNECT_CLIENT_DATA_PERIOD, - flags: SIMCONNECT_DATA_REQUEST_FLAG, - origin: DWORD, - interval: DWORD, - limit: DWORD, ) -> bool { + let title = cstring(container_title); unsafe { - SimConnect_RequestDataOnSimObject( - self.sim_connect_handle, - request_id, - define_id, - object_id, - period, - flags, - origin, - interval, - limit, - ) == 0 + SimConnect_AICreateSimulatedObject(self.handle, title.as_ptr(), init_pos, request_id) == 0 } } - pub unsafe fn set_data_on_sim_object( + pub fn ai_release_control( &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, object_id: SIMCONNECT_OBJECT_ID, - flags: SIMCONNECT_DATA_SET_FLAG, - array_count: DWORD, - size: DWORD, - pntr: *mut ::std::os::raw::c_void, + request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { - unsafe { - SimConnect_SetDataOnSimObject( - self.sim_connect_handle, - define_id, - object_id, - flags, - array_count, - size, - pntr, - ) == 0 - } + unsafe { SimConnect_AIReleaseControl(self.handle, object_id, request_id) == 0 } } - pub fn subscribe_to_system_event( + pub fn ai_remove_object( &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - event_name: &str, + object_id: SIMCONNECT_OBJECT_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { - let event_name = CString::new(event_name).unwrap(); - - unsafe { - SimConnect_SubscribeToSystemEvent( - self.sim_connect_handle, - event_id, - event_name.as_ptr(), - ) == 0 - } + unsafe { SimConnect_AIRemoveObject(self.handle, object_id, request_id) == 0 } } - pub fn map_client_event_to_sim_event( + pub fn ai_set_aircraft_flight_plan( &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - event_name: &str, + object_id: SIMCONNECT_OBJECT_ID, + flight_plan_path: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { - let event_name = CString::new(event_name).unwrap(); - + let plan = cstring(flight_plan_path); unsafe { - SimConnect_MapClientEventToSimEvent( - self.sim_connect_handle, - event_id, - event_name.as_ptr(), + SimConnect_AISetAircraftFlightPlan( + self.handle, object_id, plan.as_ptr(), request_id, ) == 0 } } - pub fn transmit_client_event( + // ==================== Weather ==================== + + pub fn weather_request_interpolated_observation( &self, - object_id: SIMCONNECT_OBJECT_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - dw_data: DWORD, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - flags: SIMCONNECT_EVENT_FLAG, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, ) -> bool { unsafe { - SimConnect_TransmitClientEvent( - self.sim_connect_handle, - object_id, - event_id, - dw_data, - group_id, - flags, - ) == 0 + SimConnect_WeatherRequestInterpolatedObservation(self.handle, request_id, lat, lon, alt) == 0 } } - pub fn add_client_event_to_notification_group( + pub fn weather_request_observation_at_station( &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - maskable: bool, + request_id: SIMCONNECT_DATA_REQUEST_ID, + station: &str, ) -> bool { + let station = cstring(station); unsafe { - SimConnect_AddClientEventToNotificationGroup( - self.sim_connect_handle, - group_id, - event_id, - maskable as i32, - ) == 0 + SimConnect_WeatherRequestObservationAtStation(self.handle, request_id, station.as_ptr()) == 0 } } - pub fn set_notification_group_priority( + pub fn weather_request_observation_at_nearest_station( &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - priority: DWORD, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, ) -> bool { unsafe { - SimConnect_SetNotificationGroupPriority(self.sim_connect_handle, group_id, priority) - == 0 + SimConnect_WeatherRequestObservationAtNearestStation(self.handle, request_id, lat, lon) == 0 } } - pub fn map_input_event_to_client_event( + pub fn weather_create_station( &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, - down_event: SIMCONNECT_CLIENT_EVENT_ID, - down_return_value: DWORD, - up_event: SIMCONNECT_CLIENT_EVENT_ID, - up_return_value: DWORD, - maskable: bool, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + name: &str, + lat: f32, + lon: f32, + alt: f32, ) -> bool { - let input_definition = CString::new(input_definition).unwrap(); + let icao_c = cstring(icao); + let name_c = cstring(name); unsafe { - SimConnect_MapInputEventToClientEvent( - self.sim_connect_handle, - group_id, - input_definition.as_ptr(), - down_event, - down_return_value, - up_event, - up_return_value, - maskable as i32, + SimConnect_WeatherCreateStation( + self.handle, + request_id, + icao_c.as_ptr(), + name_c.as_ptr(), + lat, + lon, + alt, ) == 0 } } - pub fn set_input_group_state(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, state: DWORD) -> bool { - unsafe { SimConnect_SetInputGroupState(self.sim_connect_handle, group_id, state) == 0 } + pub fn weather_remove_station(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, station: &str) -> bool { + let station = cstring(station); + unsafe { + SimConnect_WeatherRemoveStation(self.handle, request_id, station.as_ptr()) == 0 + } } - pub fn set_input_priority(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, priority: DWORD) -> bool { + pub fn weather_set_observation(&self, seconds: DWORD, observation: &str) -> bool { + let obs = cstring(observation); unsafe { - SimConnect_SetInputGroupPriority(self.sim_connect_handle, group_id, priority) == 0 + SimConnect_WeatherSetObservation(self.handle, seconds, obs.as_ptr()) == 0 } } - pub fn transmit_client_event_ex1( + pub fn weather_set_mode_server(&self, port: DWORD, seconds: DWORD) -> bool { + unsafe { SimConnect_WeatherSetModeServer(self.handle, port, seconds) == 0 } + } + + pub fn weather_set_mode_theme(&self, theme_name: &str) -> bool { + let theme = cstring(theme_name); + unsafe { SimConnect_WeatherSetModeTheme(self.handle, theme.as_ptr()) == 0 } + } + + pub fn weather_set_mode_global(&self) -> bool { + unsafe { SimConnect_WeatherSetModeGlobal(self.handle) == 0 } + } + + pub fn weather_set_mode_custom(&self) -> bool { + unsafe { SimConnect_WeatherSetModeCustom(self.handle) == 0 } + } + + pub fn weather_set_dynamic_update_rate(&self, rate: DWORD) -> bool { + unsafe { SimConnect_WeatherSetDynamicUpdateRate(self.handle, rate) == 0 } + } + + pub fn weather_request_cloud_state( &self, - object_id: SIMCONNECT_OBJECT_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - flags: SIMCONNECT_EVENT_FLAG, - data0: DWORD, - data1: DWORD, - data2: DWORD, - data3: DWORD, - data4: DWORD, + request_id: SIMCONNECT_DATA_REQUEST_ID, + min_x: f32, + min_y: f32, + min_z: f32, + max_x: f32, + max_y: f32, + max_z: f32, + flags: DWORD, ) -> bool { unsafe { - SimConnect_TransmitClientEvent_EX1( - self.sim_connect_handle, - object_id, - event_id, - group_id, - flags, - data0, - data1, - data2, - data3, - data4, + SimConnect_WeatherRequestCloudState( + self.handle, request_id, min_x, min_y, min_z, max_x, max_y, max_z, flags, ) == 0 } } - pub fn add_to_facility_definition( + pub fn weather_create_thermal( &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - field_name: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, + radius: f32, + height: f32, + core_rate: f32, + core_turbulence: f32, + sink_rate: f32, + sink_turbulence: f32, + core_size: f32, + core_transition_size: f32, + sink_layer_size: f32, + sink_transition_size: f32, ) -> bool { - let field_name = CString::new(field_name).unwrap(); unsafe { - SimConnect_AddToFacilityDefinition( - self.sim_connect_handle, - define_id, - field_name.as_ptr(), + SimConnect_WeatherCreateThermal( + self.handle, + request_id, + lat, + lon, + alt, + radius, + height, + core_rate, + core_turbulence, + sink_rate, + sink_turbulence, + core_size, + core_transition_size, + sink_layer_size, + sink_transition_size, + ) == 0 + } + } + + pub fn weather_remove_thermal(&self, object_id: SIMCONNECT_OBJECT_ID) -> bool { + unsafe { SimConnect_WeatherRemoveThermal(self.handle, object_id) == 0 } + } + + // ==================== Mission & System ==================== + + pub fn execute_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_ExecuteMissionAction(self.handle, instance_id) == 0 } + } + + pub fn complete_custom_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_CompleteCustomMissionAction(self.handle, instance_id) == 0 } + } + + pub fn request_system_state(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, state: &str) -> bool { + let state = cstring(state); + unsafe { SimConnect_RequestSystemState(self.handle, request_id, state.as_ptr()) == 0 } + } + + pub fn set_system_state(&self, state: &str, integer: DWORD, float_val: f32, string_val: &str) -> bool { + let state_c = cstring(state); + let string_c = cstring(string_val); + + unsafe { + SimConnect_SetSystemState( + self.handle, + state_c.as_ptr(), + integer, + float_val, + string_c.as_ptr(), ) == 0 } } + pub fn flight_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightLoad(self.handle, name.as_ptr()) == 0 } + } + + pub fn flight_save(&self, file_name: &str, title: &str, description: &str, flags: DWORD) -> bool { + let name = cstring(file_name); + let t = cstring(title); + let d = cstring(description); + unsafe { SimConnect_FlightSave(self.handle, name.as_ptr(), t.as_ptr(), d.as_ptr(), flags) == 0 } + } + + pub fn flight_plan_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightPlanLoad(self.handle, name.as_ptr()) == 0 } + } + + // ==================== Facilities ==================== + + pub fn subscribe_to_facilities( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_SubscribeToFacilities(self.handle, list_type, request_id) == 0 } + } + + pub fn unsubscribe_to_facilities(&self, list_type: SIMCONNECT_FACILITY_LIST_TYPE) -> bool { + unsafe { SimConnect_UnsubscribeToFacilities(self.handle, list_type) == 0 } + } + + pub fn request_facilities_list( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_RequestFacilitiesList(self.handle, list_type, request_id) == 0 } + } + + pub fn add_to_facility_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID, field_name: &str) -> bool { + let field = cstring(field_name); + unsafe { SimConnect_AddToFacilityDefinition(self.handle, define_id, field.as_ptr()) == 0 } + } + pub fn request_facility_data( &self, define_id: SIMCONNECT_DATA_DEFINITION_ID, @@ -790,12 +844,11 @@ impl SimConnector { icao: &str, region: Option<&str>, ) -> bool { - let icao = CString::new(icao).unwrap(); - let region = region.map(|s| CString::new(s).unwrap()); - + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); unsafe { SimConnect_RequestFacilityData( - self.sim_connect_handle, + self.handle, define_id, request_id, icao.as_ptr(), @@ -812,7 +865,7 @@ impl SimConnector { ) -> bool { unsafe { SimConnect_SubscribeToFacilities_EX1( - self.sim_connect_handle, + self.handle, list_type, new_in_range_request_id, old_out_of_range_request_id, @@ -828,7 +881,7 @@ impl SimConnector { ) -> bool { unsafe { SimConnect_UnsubscribeToFacilities_EX1( - self.sim_connect_handle, + self.handle, list_type, unsubscribe_new_in_range, unsubscribe_old_out_of_range, @@ -842,8 +895,7 @@ impl SimConnector { request_id: SIMCONNECT_DATA_REQUEST_ID, ) -> bool { unsafe { - SimConnect_RequestFacilitiesList_EX1(self.sim_connect_handle, list_type, request_id) - == 0 + SimConnect_RequestFacilitiesList_EX1(self.handle, list_type, request_id) == 0 } } @@ -855,12 +907,11 @@ impl SimConnector { region: Option<&str>, type_: Option, ) -> bool { - let icao = CString::new(icao).unwrap(); - let region = region.map(|s| CString::new(s).unwrap()); - + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); unsafe { SimConnect_RequestFacilityData_EX1( - self.sim_connect_handle, + self.handle, define_id, request_id, icao.as_ptr(), @@ -876,72 +927,107 @@ impl SimConnector { array_count: DWORD, indexes: *mut i32, ) -> bool { - let airport_icao = CString::new(airport_icao).unwrap(); + let icao = cstring(airport_icao); unsafe { - SimConnect_RequestJetwayData( - self.sim_connect_handle, - airport_icao.as_ptr(), - array_count, - indexes, - ) == 0 + SimConnect_RequestJetwayData(self.handle, icao.as_ptr(), array_count, indexes) == 0 } } - pub fn enumerate_controllers(&self) -> bool { - unsafe { SimConnect_EnumerateControllers(self.sim_connect_handle) == 0 } + pub fn add_facility_data_definition_filter( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + filter_path: &str, + filter_data: *const std::os::raw::c_void, + cb_unit_size: DWORD, + ) -> bool { + let path = cstring(filter_path); + unsafe { + SimConnect_AddFacilityDataDefinitionFilter( + self.handle, + define_id, + path.as_ptr(), + cb_unit_size, + filter_data as *mut _, + ) == 0 + } } - pub fn map_input_event_to_client_event_ex1( + pub fn clear_all_facility_data_definition_filters( &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, - down_event: SIMCONNECT_CLIENT_EVENT_ID, - down_return_value: DWORD, - up_event: SIMCONNECT_CLIENT_EVENT_ID, - up_return_value: DWORD, - maskable: bool, + define_id: SIMCONNECT_DATA_DEFINITION_ID, ) -> bool { - let input_definition = CString::new(input_definition).unwrap(); + unsafe { + SimConnect_ClearAllFacilityDataDefinitionFilters(self.handle, define_id) == 0 + } + } + // ==================== Camera ==================== + + pub fn camera_set_relative_6dof( + &self, + delta_x: f32, + delta_y: f32, + delta_z: f32, + pitch: f32, + bank: f32, + heading: f32, + ) -> bool { unsafe { - SimConnect_MapInputEventToClientEvent_EX1( - self.sim_connect_handle, - group_id, - input_definition.as_ptr(), - down_event, - down_return_value, - up_event, - up_return_value, - maskable as i32, + SimConnect_CameraSetRelative6DOF( + self.handle, delta_x, delta_y, delta_z, pitch, bank, heading, ) == 0 } } - pub unsafe fn execute_action( + // ==================== Menu ==================== + + pub fn menu_add_item( &self, - request_id: DWORD, - action_id: &str, - unit_size: DWORD, - param_values: *mut std::os::raw::c_void, + menu_item: &str, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, + ) -> bool { + let item = cstring(menu_item); + unsafe { SimConnect_MenuAddItem(self.handle, item.as_ptr(), event_id, data) == 0 } + } + + pub fn menu_add_sub_item( + &self, + menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + menu_item: &str, + sub_menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, ) -> bool { - let action_id = CString::new(action_id).unwrap(); + let item = cstring(menu_item); unsafe { - SimConnect_ExecuteAction( - self.sim_connect_handle, - request_id, - action_id.as_ptr(), - unit_size, - param_values, - ) == 0 + SimConnect_MenuAddSubItem(self.handle, menu_event_id, item.as_ptr(), sub_menu_event_id, data) == 0 } } + pub fn menu_delete_item(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_MenuDeleteItem(self.handle, event_id) == 0 } + } + + pub fn menu_delete_sub_item( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + sub_event_id: SIMCONNECT_CLIENT_EVENT_ID, + ) -> bool { + unsafe { SimConnect_MenuDeleteSubItem(self.handle, event_id, sub_event_id) == 0 } + } + + // ==================== Other ==================== + + pub fn enumerate_controllers(&self) -> bool { + unsafe { SimConnect_EnumerateControllers(self.handle) == 0 } + } + pub fn enumerate_input_events(&self, request_id: SIMCONNECT_DATA_REQUEST_ID) -> bool { - unsafe { SimConnect_EnumerateInputEvents(self.sim_connect_handle, request_id) == 0 } + unsafe { SimConnect_EnumerateInputEvents(self.handle, request_id) == 0 } } pub fn get_input_event(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, hash: u64) -> bool { - unsafe { SimConnect_GetInputEvent(self.sim_connect_handle, request_id, hash) == 0 } + unsafe { SimConnect_GetInputEvent(self.handle, request_id, hash) == 0 } } pub unsafe fn set_input_event( @@ -950,247 +1036,143 @@ impl SimConnector { unit_size: DWORD, value: *mut std::os::raw::c_void, ) -> bool { - unsafe { SimConnect_SetInputEvent(self.sim_connect_handle, hash, unit_size, value) == 0 } + unsafe { SimConnect_SetInputEvent(self.handle, hash, unit_size, value) == 0 } } pub fn subscribe_input_event(&self, hash: u64) -> bool { - unsafe { SimConnect_SubscribeInputEvent(self.sim_connect_handle, hash) == 0 } + unsafe { SimConnect_SubscribeInputEvent(self.handle, hash) == 0 } } pub fn unsubscribe_input_event(&self, hash: u64) -> bool { - unsafe { SimConnect_UnsubscribeInputEvent(self.sim_connect_handle, hash) == 0 } + unsafe { SimConnect_UnsubscribeInputEvent(self.handle, hash) == 0 } } pub fn enumerate_input_event_params(&self, hash: u64) -> bool { - unsafe { SimConnect_EnumerateInputEventParams(self.sim_connect_handle, hash) == 0 } + unsafe { SimConnect_EnumerateInputEventParams(self.handle, hash) == 0 } } - pub fn add_facility_data_definition_filter( + pub unsafe fn execute_action( &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - filter_path: &str, - filter_data: *const std::os::raw::c_void, - cb_unit_size: DWORD, + request_id: DWORD, + action_id: &str, + unit_size: DWORD, + param_values: *mut std::os::raw::c_void, ) -> bool { - let filter_path = CString::new(filter_path).unwrap(); + let action = cstring(action_id); unsafe { - SimConnect_AddFacilityDataDefinitionFilter( - self.sim_connect_handle, - define_id, - filter_path.as_ptr(), - cb_unit_size, - filter_data as *mut _, - ) == 0 + SimConnect_ExecuteAction(self.handle, request_id, action.as_ptr(), unit_size, param_values) == 0 } } - pub fn clear_all_facility_data_definition_filters( + pub unsafe fn text( &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, + text_type: SIMCONNECT_TEXT_TYPE, + time_in_seconds: f32, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + unit_size: DWORD, + data_set: *mut std::os::raw::c_void, ) -> bool { unsafe { - SimConnect_ClearAllFacilityDataDefinitionFilters(self.sim_connect_handle, define_id) - == 0 + SimConnect_Text(self.handle, text_type, time_in_seconds, event_id, unit_size, data_set) == 0 } } - /// Retrieves the next message from SimConnect. Nonblocking. - pub fn get_next_message(&self) -> Result, &str> { - let mut data_buf: *mut SIMCONNECT_RECV = ptr::null_mut(); - let mut size_buf: DWORD = 0; - let size_buf_pointer: *mut DWORD = &mut size_buf; + pub unsafe fn get_last_sent_packet_id(&self, error: *mut DWORD) -> bool { + unsafe { SimConnect_GetLastSentPacketID(self.handle, error) == 0 } + } + + pub unsafe fn call_dispatch( + &self, + dispatch_callback: DispatchProc, + context: *mut std::os::raw::c_void, + ) -> bool { + unsafe { SimConnect_CallDispatch(self.handle, dispatch_callback, context) == 0 } + } + + pub unsafe fn request_response_times(&self, count: DWORD, elapsed_seconds: *mut f32) -> bool { + unsafe { SimConnect_RequestResponseTimes(self.handle, count, elapsed_seconds) == 0 } + } + // ==================== String Utilities ==================== + + pub unsafe fn retrieve_string( + p_data: *mut SIMCONNECT_RECV, + cb_data: DWORD, + p_string_v: *mut std::os::raw::c_void, + psz_string: *mut *mut std::os::raw::c_char, + pcb_string: *mut DWORD, + ) -> bool { + unsafe { + SimConnect_RetrieveString(p_data, cb_data, p_string_v, psz_string, pcb_string) == 0 + } + } + + pub unsafe fn insert_string( + p_dest: *mut std::os::raw::c_char, + cb_dest: DWORD, + pp_end: *mut *mut std::os::raw::c_void, + pcb_string: *mut DWORD, + p_source: *const std::os::raw::c_char, + ) -> bool { + unsafe { + SimConnect_InsertString(p_dest, cb_dest, pp_end, pcb_string, p_source) == 0 + } + } + + // ==================== Main Message Loop ==================== + + pub fn get_next_message(&self) -> Result, &str> { unsafe { - let result = SimConnect_GetNextDispatch( - self.sim_connect_handle, - &mut data_buf, - size_buf_pointer, - ); - - if result != 0 { - return Err("Failed getting data!"); + let mut data_buf: *mut SIMCONNECT_RECV = ptr::null_mut(); + let mut size_buf: DWORD = 0; + + if SimConnect_GetNextDispatch(self.handle, &mut data_buf, &mut size_buf) != 0 { + return Err("Failed getting data from SimConnect"); } - // SimConnect_GetNextDispatch returns S_OK with a NULL pointer when the queue is empty. - // Dereferencing a null pointer would be UB, so we must check this explicitly. if data_buf.is_null() { return Ok(DispatchResult::Null); } match (*data_buf).dwID as SIMCONNECT_RECV_ID { SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(DispatchResult::Null), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => Ok(DispatchResult::Exception( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_EXCEPTION)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Ok(DispatchResult::Open( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_OPEN)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Ok(DispatchResult::Quit( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_QUIT)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => Ok(DispatchResult::Event( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_EVENT)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE => { - Ok(DispatchResult::EventObjectAddRemove(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FILENAME => { - Ok(DispatchResult::EventFilename(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_FILENAME), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FRAME => { - Ok(DispatchResult::EventFrame(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_FRAME), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => { - Ok(DispatchResult::SimObjectData(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE => { - Ok(DispatchResult::SimObjectDataByType(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WEATHER_OBSERVATION => { - Ok(DispatchResult::WeatherObservation(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_WEATHER_OBSERVATION), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLOUD_STATE => { - Ok(DispatchResult::CloudState(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_CLOUD_STATE), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID => { - Ok(DispatchResult::AssignedObjectId(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_ASSIGNED_OBJECT_ID), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_RESERVED_KEY => { - Ok(DispatchResult::ReservedKey(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_RESERVED_KEY), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CUSTOM_ACTION => { - Ok(DispatchResult::CustomAction(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_CUSTOM_ACTION), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SYSTEM_STATE => { - Ok(DispatchResult::SystemState(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_SYSTEM_STATE), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLIENT_DATA => { - Ok(DispatchResult::ClientData(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_CLIENT_DATA), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE => { - Ok(DispatchResult::EventWeatherMode(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_WEATHER_MODE), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => { - Ok(DispatchResult::AirportList(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_AIRPORT_LIST), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_VOR_LIST => Ok(DispatchResult::VorList( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_VOR_LIST)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NDB_LIST => Ok(DispatchResult::NdbList( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_NDB_LIST)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WAYPOINT_LIST => { - Ok(DispatchResult::WaypointList(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_WAYPOINT_LIST), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED => Ok( - DispatchResult::EventMultiplayerServerStarted(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED), - )), - ), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED => Ok( - DispatchResult::EventMultiplayerClientStarted(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED), - )), - ), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED => Ok( - DispatchResult::EventMultiplayerSessionEnded(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED), - )), - ), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_END => { - Ok(DispatchResult::EventRaceEnd(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_END), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_LAP => { - Ok(DispatchResult::EventRaceLap(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_LAP), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_EX1 => Ok(DispatchResult::EventEx1( - transmute_copy(&(data_buf as *const SIMCONNECT_RECV_EVENT_EX1)), - )), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA => { - Ok(DispatchResult::FacilityData(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA_END => { - Ok(DispatchResult::FacilityDataEnd(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA_END), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST => { - Ok(DispatchResult::FacilityMinimalList(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_FACILITY_MINIMAL_LIST), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_JETWAY_DATA => { - Ok(DispatchResult::JetwayData(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_JETWAY_DATA), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CONTROLLERS_LIST => { - Ok(DispatchResult::ControllersList(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_CONTROLLERS_LIST), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ACTION_CALLBACK => { - Ok(DispatchResult::ActionCallback(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_ACTION_CALLBACK), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS => { - Ok(DispatchResult::EnumerateInputEvents(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_GET_INPUT_EVENT => { - Ok(DispatchResult::GetInputEvent(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_GET_INPUT_EVENT), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT => { - Ok(DispatchResult::SubscribeInputEvent(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT), - ))) - } - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS => { - Ok(DispatchResult::EnumerateInputEventParams(transmute_copy( - &(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS), - ))) - } - + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => Ok(DispatchResult::Exception(&*(data_buf as *const SIMCONNECT_RECV_EXCEPTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Ok(DispatchResult::Open(&*(data_buf as *const SIMCONNECT_RECV_OPEN))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Ok(DispatchResult::Quit(&*(data_buf as *const SIMCONNECT_RECV_QUIT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => Ok(DispatchResult::Event(&*(data_buf as *const SIMCONNECT_RECV_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE => Ok(DispatchResult::EventObjectAddRemove(&*(data_buf as *const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FILENAME => Ok(DispatchResult::EventFilename(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FILENAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FRAME => Ok(DispatchResult::EventFrame(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FRAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => Ok(DispatchResult::SimObjectData(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE => Ok(DispatchResult::SimObjectDataByType(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WEATHER_OBSERVATION => Ok(DispatchResult::WeatherObservation(&*(data_buf as *const SIMCONNECT_RECV_WEATHER_OBSERVATION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLOUD_STATE => Ok(DispatchResult::CloudState(&*(data_buf as *const SIMCONNECT_RECV_CLOUD_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID => Ok(DispatchResult::AssignedObjectId(&*(data_buf as *const SIMCONNECT_RECV_ASSIGNED_OBJECT_ID))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_RESERVED_KEY => Ok(DispatchResult::ReservedKey(&*(data_buf as *const SIMCONNECT_RECV_RESERVED_KEY))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CUSTOM_ACTION => Ok(DispatchResult::CustomAction(&*(data_buf as *const SIMCONNECT_RECV_CUSTOM_ACTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SYSTEM_STATE => Ok(DispatchResult::SystemState(&*(data_buf as *const SIMCONNECT_RECV_SYSTEM_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLIENT_DATA => Ok(DispatchResult::ClientData(&*(data_buf as *const SIMCONNECT_RECV_CLIENT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE => Ok(DispatchResult::EventWeatherMode(&*(data_buf as *const SIMCONNECT_RECV_EVENT_WEATHER_MODE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => Ok(DispatchResult::AirportList(&*(data_buf as *const SIMCONNECT_RECV_AIRPORT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_VOR_LIST => Ok(DispatchResult::VorList(&*(data_buf as *const SIMCONNECT_RECV_VOR_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NDB_LIST => Ok(DispatchResult::NdbList(&*(data_buf as *const SIMCONNECT_RECV_NDB_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WAYPOINT_LIST => Ok(DispatchResult::WaypointList(&*(data_buf as *const SIMCONNECT_RECV_WAYPOINT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED => Ok(DispatchResult::EventMultiplayerServerStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED => Ok(DispatchResult::EventMultiplayerClientStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED => Ok(DispatchResult::EventMultiplayerSessionEnded(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_END => Ok(DispatchResult::EventRaceEnd(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_LAP => Ok(DispatchResult::EventRaceLap(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_LAP))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_EX1 => Ok(DispatchResult::EventEx1(&*(data_buf as *const SIMCONNECT_RECV_EVENT_EX1))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA => Ok(DispatchResult::FacilityData(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA_END => Ok(DispatchResult::FacilityDataEnd(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST => Ok(DispatchResult::FacilityMinimalList(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_MINIMAL_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_JETWAY_DATA => Ok(DispatchResult::JetwayData(&*(data_buf as *const SIMCONNECT_RECV_JETWAY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ACTION_CALLBACK => Ok(DispatchResult::ActionCallback(&*(data_buf as *const SIMCONNECT_RECV_ACTION_CALLBACK))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS => Ok(DispatchResult::EnumerateInputEvents(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_GET_INPUT_EVENT => Ok(DispatchResult::GetInputEvent(&*(data_buf as *const SIMCONNECT_RECV_GET_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT => Ok(DispatchResult::SubscribeInputEvent(&*(data_buf as *const SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS => Ok(DispatchResult::EnumerateInputEventParams(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CONTROLLERS_LIST => Ok(DispatchResult::ControllersList(&*(data_buf as *const SIMCONNECT_RECV_CONTROLLERS_LIST))), _ => Err("Unhandled RECV_ID"), } } @@ -1199,8 +1181,13 @@ impl SimConnector { impl Drop for SimConnector { fn drop(&mut self) { - if !self.sim_connect_handle.is_null() { - self.close(); + if !self.handle.is_null() { + let _ = self.close(); } } } + +#[inline] +fn cstring(s: &str) -> CString { + CString::new(s).expect("string contained interior nul byte") +} \ No newline at end of file From 939f2ecd21013bd9919a5125b7963b6a08da2eb1 Mon Sep 17 00:00:00 2001 From: Randy T <47700786+rthom91@users.noreply.github.com> Date: Sun, 12 Jul 2026 03:34:38 -0400 Subject: [PATCH 7/7] Split + Add FS2024 --- Cargo.lock | 31 +- Cargo.toml | 21 +- simulators/FS2020/Cargo.toml | 10 + .../FS2020/SimConnect.dll | Bin build.rs => simulators/FS2020/build.rs | 7 +- .../FS2020/libsrc}/include/SimConnect.hpp | 0 .../FS2020/libsrc}/lib/SimConnect.lib | Bin simulators/FS2020/src/lib.rs | 1193 ++++++++++++++ simulators/FS2024/Cargo.toml | 10 + simulators/FS2024/SimConnect.dll | Bin 0 -> 85504 bytes simulators/FS2024/build.rs | 361 +++++ .../FS2024/libsrc/include/SimConnect.hpp | 1160 +++++++++++++ simulators/FS2024/libsrc/lib/SimConnect.lib | Bin 0 -> 35288 bytes simulators/FS2024/src/lib.rs | 1436 +++++++++++++++++ src/lib.rs | 1196 +------------- 15 files changed, 4210 insertions(+), 1215 deletions(-) create mode 100644 simulators/FS2020/Cargo.toml rename SimConnect.dll => simulators/FS2020/SimConnect.dll (100%) rename build.rs => simulators/FS2020/build.rs (98%) rename {libsrc => simulators/FS2020/libsrc}/include/SimConnect.hpp (100%) rename {libsrc => simulators/FS2020/libsrc}/lib/SimConnect.lib (100%) create mode 100644 simulators/FS2020/src/lib.rs create mode 100644 simulators/FS2024/Cargo.toml create mode 100644 simulators/FS2024/SimConnect.dll create mode 100644 simulators/FS2024/build.rs create mode 100644 simulators/FS2024/libsrc/include/SimConnect.hpp create mode 100644 simulators/FS2024/libsrc/lib/SimConnect.lib create mode 100644 simulators/FS2024/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d662df3..e42146b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,9 +108,9 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "minimal-lexical" @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.4" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -187,9 +187,9 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "shlex" @@ -200,6 +200,21 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simconnect" version = "0.5.0" +dependencies = [ + "simconnect-fs2020", + "simconnect-fs2024", +] + +[[package]] +name = "simconnect-fs2020" +version = "0.5.0" +dependencies = [ + "bindgen", +] + +[[package]] +name = "simconnect-fs2024" +version = "0.5.0" dependencies = [ "bindgen", ] diff --git a/Cargo.toml b/Cargo.toml index 8d08e3a..89ba20a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,17 +6,12 @@ version = "0.5.0" authors = ["Connor T"] edition = "2021" -[[example]] -name = "aircraft_updates_on_change" -path = "examples/aircraft_updates_on_change/main.rs" +[dependencies] +simconnect-fs2020 = { path = "simulators/FS2020", optional = true } +simconnect-fs2024 = { path = "simulators/FS2024", optional = true } -[[example]] -name = "aircraft_updates" -path = "examples/aircraft_updates/main.rs" - -[[example]] -name = "aircraft_inputs" -path = "examples/aircraft_inputs/main.rs" - -[build-dependencies] -bindgen = "0.72" +[features] +default = ["all"] +fs2020 = ["dep:simconnect-fs2020"] +fs2024 = ["dep:simconnect-fs2024"] +all = ["fs2020", "fs2024"] diff --git a/simulators/FS2020/Cargo.toml b/simulators/FS2020/Cargo.toml new file mode 100644 index 0000000..08669d2 --- /dev/null +++ b/simulators/FS2020/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "simconnect-fs2020" +license = "MIT" +description = "Rust bindings for SimConnect" +version = "0.5.0" +authors = ["Connor T"] +edition = "2021" + +[build-dependencies] +bindgen = "0.72" diff --git a/SimConnect.dll b/simulators/FS2020/SimConnect.dll similarity index 100% rename from SimConnect.dll rename to simulators/FS2020/SimConnect.dll diff --git a/build.rs b/simulators/FS2020/build.rs similarity index 98% rename from build.rs rename to simulators/FS2020/build.rs index f65b5f4..a043df0 100644 --- a/build.rs +++ b/simulators/FS2020/build.rs @@ -1,7 +1,10 @@ use std::{env, path::PathBuf}; fn main() { - println!("cargo:rustc-link-search=libsrc/lib"); + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let lib_dir = PathBuf::from(manifest_dir).join("libsrc").join("lib"); + + println!("cargo:rustc-link-search={}", lib_dir.display()); println!("cargo:rustc-link-lib=static=SimConnect"); let handle = std::thread::Builder::new() @@ -299,4 +302,4 @@ fn main() { .expect("Failed to spawn bindgen thread"); handle.join().expect("Bindgen thread panicked"); -} \ No newline at end of file +} diff --git a/libsrc/include/SimConnect.hpp b/simulators/FS2020/libsrc/include/SimConnect.hpp similarity index 100% rename from libsrc/include/SimConnect.hpp rename to simulators/FS2020/libsrc/include/SimConnect.hpp diff --git a/libsrc/lib/SimConnect.lib b/simulators/FS2020/libsrc/lib/SimConnect.lib similarity index 100% rename from libsrc/lib/SimConnect.lib rename to simulators/FS2020/libsrc/lib/SimConnect.lib diff --git a/simulators/FS2020/src/lib.rs b/simulators/FS2020/src/lib.rs new file mode 100644 index 0000000..a3169ad --- /dev/null +++ b/simulators/FS2020/src/lib.rs @@ -0,0 +1,1193 @@ +#![allow(clippy::too_many_arguments, clippy::missing_safety_doc)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::ffi::CString; +use std::ptr; + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[derive(Debug)] +pub enum DispatchResult<'a> { + Null, + Exception(&'a SIMCONNECT_RECV_EXCEPTION), + Open(&'a SIMCONNECT_RECV_OPEN), + Quit(&'a SIMCONNECT_RECV_QUIT), + Event(&'a SIMCONNECT_RECV_EVENT), + EventObjectAddRemove(&'a SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE), + EventFilename(&'a SIMCONNECT_RECV_EVENT_FILENAME), + EventFrame(&'a SIMCONNECT_RECV_EVENT_FRAME), + SimObjectData(&'a SIMCONNECT_RECV_SIMOBJECT_DATA), + SimObjectDataByType(&'a SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE), + WeatherObservation(&'a SIMCONNECT_RECV_WEATHER_OBSERVATION), + CloudState(&'a SIMCONNECT_RECV_CLOUD_STATE), + AssignedObjectId(&'a SIMCONNECT_RECV_ASSIGNED_OBJECT_ID), + ReservedKey(&'a SIMCONNECT_RECV_RESERVED_KEY), + CustomAction(&'a SIMCONNECT_RECV_CUSTOM_ACTION), + SystemState(&'a SIMCONNECT_RECV_SYSTEM_STATE), + ClientData(&'a SIMCONNECT_RECV_CLIENT_DATA), + EventWeatherMode(&'a SIMCONNECT_RECV_EVENT_WEATHER_MODE), + AirportList(&'a SIMCONNECT_RECV_AIRPORT_LIST), + VorList(&'a SIMCONNECT_RECV_VOR_LIST), + NdbList(&'a SIMCONNECT_RECV_NDB_LIST), + WaypointList(&'a SIMCONNECT_RECV_WAYPOINT_LIST), + EventMultiplayerServerStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED), + EventMultiplayerClientStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED), + EventMultiplayerSessionEnded(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED), + EventRaceEnd(&'a SIMCONNECT_RECV_EVENT_RACE_END), + EventRaceLap(&'a SIMCONNECT_RECV_EVENT_RACE_LAP), + EventEx1(&'a SIMCONNECT_RECV_EVENT_EX1), + FacilityData(&'a SIMCONNECT_RECV_FACILITY_DATA), + FacilityDataEnd(&'a SIMCONNECT_RECV_FACILITY_DATA_END), + FacilityMinimalList(&'a SIMCONNECT_RECV_FACILITY_MINIMAL_LIST), + JetwayData(&'a SIMCONNECT_RECV_JETWAY_DATA), + ActionCallback(&'a SIMCONNECT_RECV_ACTION_CALLBACK), + EnumerateInputEvents(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS), + GetInputEvent(&'a SIMCONNECT_RECV_GET_INPUT_EVENT), + SubscribeInputEvent(&'a SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT), + EnumerateInputEventParams(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS), + ControllersList(&'a SIMCONNECT_RECV_CONTROLLERS_LIST), +} + +#[derive(Debug)] +pub struct SimConnector { + handle: HANDLE, +} + +impl Default for SimConnector { + fn default() -> Self { + Self { handle: ptr::null_mut() } + } +} + +impl SimConnector { + pub fn new() -> Self { + Self::default() + } + + // ==================== Connection & Lifecycle ==================== + + pub fn connect(&mut self, program_name: &str) -> bool { + let name = cstring(program_name); + + unsafe { + SimConnect_Open( + &mut self.handle, + name.as_ptr(), + ptr::null_mut(), + 0, + ptr::null_mut(), + 0, + ) == 0 + } + } + + pub fn close(&mut self) -> bool { + if self.handle.is_null() { + return true; + } + let result = unsafe { SimConnect_Close(self.handle) == 0 }; + self.handle = ptr::null_mut(); + result + } + + // ==================== Data Definition ==================== + + pub fn add_data_definition( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + datum_name: &str, + units_name: &str, + datum_type: SIMCONNECT_DATATYPE, + epsilon: f32, + datum_id: DWORD, + ) -> bool { + let name = cstring(datum_name); + let units = cstring(units_name); + + unsafe { + SimConnect_AddToDataDefinition( + self.handle, + define_id, + name.as_ptr(), + units.as_ptr(), + datum_type, + epsilon, + datum_id, + ) == 0 + } + } + + pub fn clear_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { + unsafe { SimConnect_ClearDataDefinition(self.handle, define_id) == 0 } + } + + // ==================== Events ==================== + + pub fn map_client_event_to_sim_event( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, + ) -> bool { + let name = cstring(event_name); + unsafe { SimConnect_MapClientEventToSimEvent(self.handle, event_id, name.as_ptr()) == 0 } + } + + pub fn subscribe_to_system_event( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, + ) -> bool { + let name = cstring(event_name); + unsafe { + SimConnect_SubscribeToSystemEvent(self.handle, event_id, name.as_ptr()) == 0 + } + } + + pub fn unsubscribe_from_system_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_UnsubscribeFromSystemEvent(self.handle, event_id) == 0 } + } + + pub fn set_system_event_state( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + state: SIMCONNECT_STATE, + ) -> bool { + unsafe { SimConnect_SetSystemEventState(self.handle, event_id, state) == 0 } + } + + pub fn transmit_client_event( + &self, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + dw_data: DWORD, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, + ) -> bool { + unsafe { + SimConnect_TransmitClientEvent( + self.handle, + object_id, + event_id, + dw_data, + group_id, + flags, + ) == 0 + } + } + + pub fn add_client_event_to_notification_group( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + maskable: bool, + ) -> bool { + unsafe { + SimConnect_AddClientEventToNotificationGroup( + self.handle, + group_id, + event_id, + maskable as i32, + ) == 0 + } + } + + pub fn set_notification_group_priority( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + priority: DWORD, + ) -> bool { + unsafe { + SimConnect_SetNotificationGroupPriority(self.handle, group_id, priority) == 0 + } + } + + pub fn remove_client_event( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + ) -> bool { + unsafe { SimConnect_RemoveClientEvent(self.handle, group_id, event_id) == 0 } + } + + pub fn clear_notification_group(&self, group_id: SIMCONNECT_NOTIFICATION_GROUP_ID) -> bool { + unsafe { SimConnect_ClearNotificationGroup(self.handle, group_id) == 0 } + } + + pub fn request_notification_group( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + reserved: DWORD, + flags: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestNotificationGroup(self.handle, group_id, reserved, flags) == 0 + } + } + + pub fn transmit_client_event_ex1( + &self, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, + data0: DWORD, + data1: DWORD, + data2: DWORD, + data3: DWORD, + data4: DWORD, + ) -> bool { + unsafe { + SimConnect_TransmitClientEvent_EX1( + self.handle, + object_id, + event_id, + group_id, + flags, + data0, + data1, + data2, + data3, + data4, + ) == 0 + } + } + + pub fn request_reserved_key( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + key_choice1: &str, + key_choice2: &str, + key_choice3: &str, + ) -> bool { + let k1 = cstring(key_choice1); + let k2 = cstring(key_choice2); + let k3 = cstring(key_choice3); + + unsafe { + SimConnect_RequestReservedKey( + self.handle, + event_id, + k1.as_ptr(), + k2.as_ptr(), + k3.as_ptr(), + ) == 0 + } + } + + // ==================== Input Events ==================== + + pub fn map_input_event_to_client_event( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_MapInputEventToClientEvent( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, + ) == 0 + } + } + + pub fn map_input_event_to_client_event_ex1( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_MapInputEventToClientEvent_EX1( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, + ) == 0 + } + } + + pub fn set_input_group_state(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, state: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupState(self.handle, group_id, state) == 0 } + } + + pub fn set_input_priority(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, priority: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupPriority(self.handle, group_id, priority) == 0 } + } + + pub fn remove_input_event( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_RemoveInputEvent(self.handle, group_id, input.as_ptr()) == 0 + } + } + + pub fn clear_input_group(&self, group_id: SIMCONNECT_INPUT_GROUP_ID) -> bool { + unsafe { SimConnect_ClearInputGroup(self.handle, group_id) == 0 } + } + + // ==================== Data Requests ==================== + + pub fn request_data_on_sim_object( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + period: SIMCONNECT_PERIOD, + flags: SIMCONNECT_DATA_REQUEST_FLAG, + origin: DWORD, + interval: DWORD, + limit: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestDataOnSimObject( + self.handle, + request_id, + define_id, + object_id, + period, + flags, + origin, + interval, + limit, + ) == 0 + } + } + + pub fn request_data_on_sim_object_type( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + radius_in_meters: DWORD, + object_type: SIMCONNECT_SIMOBJECT_TYPE, + ) -> bool { + unsafe { + SimConnect_RequestDataOnSimObjectType( + self.handle, + request_id, + define_id, + radius_in_meters, + object_type, + ) == 0 + } + } + + pub unsafe fn set_data_on_sim_object( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + flags: SIMCONNECT_DATA_SET_FLAG, + array_count: DWORD, + size: DWORD, + pntr: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_SetDataOnSimObject( + self.handle, define_id, object_id, flags, array_count, size, pntr, + ) == 0 + } + } + + // ==================== Client Data ==================== + + pub fn create_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + size: DWORD, + flags: SIMCONNECT_CREATE_CLIENT_DATA_FLAG, + ) -> bool { + unsafe { SimConnect_CreateClientData(self.handle, data_id, size, flags) == 0 } + } + + pub fn map_client_data_name_to_id( + &self, + client_data_name: &str, + data_id: SIMCONNECT_CLIENT_DATA_ID, + ) -> bool { + let name = cstring(client_data_name); + unsafe { + SimConnect_MapClientDataNameToID(self.handle, name.as_ptr(), data_id) == 0 + } + } + + pub fn add_to_client_data_definition( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + offset: DWORD, + size_or_type: DWORD, + epsilon: f32, + datum_id: DWORD, + ) -> bool { + unsafe { + SimConnect_AddToClientDataDefinition( + self.handle, define_id, offset, size_or_type, epsilon, datum_id, + ) == 0 + } + } + + pub fn clear_client_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { + unsafe { SimConnect_ClearClientDataDefinition(self.handle, define_id) == 0 } + } + + pub fn request_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + period: SIMCONNECT_CLIENT_DATA_PERIOD, + flags: SIMCONNECT_CLIENT_DATA_REQUEST_FLAG, + origin: DWORD, + interval: DWORD, + limit: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestClientData( + self.handle, + data_id, + request_id, + define_id, + period, + flags, + origin, + interval, + limit, + ) == 0 + } + } + + pub unsafe fn set_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + flags: DWORD, + reserved: DWORD, + unit_size: DWORD, + data_set: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_SetClientData( + self.handle, data_id, define_id, flags, reserved, unit_size, data_set, + ) == 0 + } + } + + // ==================== AI Objects ==================== + + pub fn ai_create_parked_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + airport_id: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let airport = cstring(airport_id); + + unsafe { + SimConnect_AICreateParkedATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + airport.as_ptr(), + request_id, + ) == 0 + } + } + + pub fn ai_create_enroute_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + flight_number: i32, + flight_plan_path: &str, + flight_plan_position: f64, + touch_and_go: bool, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let plan = cstring(flight_plan_path); + + unsafe { + SimConnect_AICreateEnrouteATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + flight_number, + plan.as_ptr(), + flight_plan_position, + touch_and_go as i32, + request_id, + ) == 0 + } + } + + pub fn ai_create_non_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + + unsafe { + SimConnect_AICreateNonATCAircraft( + self.handle, title.as_ptr(), tail.as_ptr(), init_pos, request_id, + ) == 0 + } + } + + pub fn ai_create_simulated_object( + &self, + container_title: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + unsafe { + SimConnect_AICreateSimulatedObject(self.handle, title.as_ptr(), init_pos, request_id) == 0 + } + } + + pub fn ai_release_control( + &self, + object_id: SIMCONNECT_OBJECT_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_AIReleaseControl(self.handle, object_id, request_id) == 0 } + } + + pub fn ai_remove_object( + &self, + object_id: SIMCONNECT_OBJECT_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_AIRemoveObject(self.handle, object_id, request_id) == 0 } + } + + pub fn ai_set_aircraft_flight_plan( + &self, + object_id: SIMCONNECT_OBJECT_ID, + flight_plan_path: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let plan = cstring(flight_plan_path); + unsafe { + SimConnect_AISetAircraftFlightPlan( + self.handle, object_id, plan.as_ptr(), request_id, + ) == 0 + } + } + + // ==================== Weather ==================== + + pub fn weather_request_interpolated_observation( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, + ) -> bool { + unsafe { + SimConnect_WeatherRequestInterpolatedObservation(self.handle, request_id, lat, lon, alt) == 0 + } + } + + pub fn weather_request_observation_at_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + station: &str, + ) -> bool { + let station = cstring(station); + unsafe { + SimConnect_WeatherRequestObservationAtStation(self.handle, request_id, station.as_ptr()) == 0 + } + } + + pub fn weather_request_observation_at_nearest_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + ) -> bool { + unsafe { + SimConnect_WeatherRequestObservationAtNearestStation(self.handle, request_id, lat, lon) == 0 + } + } + + pub fn weather_create_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + name: &str, + lat: f32, + lon: f32, + alt: f32, + ) -> bool { + let icao_c = cstring(icao); + let name_c = cstring(name); + + unsafe { + SimConnect_WeatherCreateStation( + self.handle, + request_id, + icao_c.as_ptr(), + name_c.as_ptr(), + lat, + lon, + alt, + ) == 0 + } + } + + pub fn weather_remove_station(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, station: &str) -> bool { + let station = cstring(station); + unsafe { + SimConnect_WeatherRemoveStation(self.handle, request_id, station.as_ptr()) == 0 + } + } + + pub fn weather_set_observation(&self, seconds: DWORD, observation: &str) -> bool { + let obs = cstring(observation); + unsafe { + SimConnect_WeatherSetObservation(self.handle, seconds, obs.as_ptr()) == 0 + } + } + + pub fn weather_set_mode_server(&self, port: DWORD, seconds: DWORD) -> bool { + unsafe { SimConnect_WeatherSetModeServer(self.handle, port, seconds) == 0 } + } + + pub fn weather_set_mode_theme(&self, theme_name: &str) -> bool { + let theme = cstring(theme_name); + unsafe { SimConnect_WeatherSetModeTheme(self.handle, theme.as_ptr()) == 0 } + } + + pub fn weather_set_mode_global(&self) -> bool { + unsafe { SimConnect_WeatherSetModeGlobal(self.handle) == 0 } + } + + pub fn weather_set_mode_custom(&self) -> bool { + unsafe { SimConnect_WeatherSetModeCustom(self.handle) == 0 } + } + + pub fn weather_set_dynamic_update_rate(&self, rate: DWORD) -> bool { + unsafe { SimConnect_WeatherSetDynamicUpdateRate(self.handle, rate) == 0 } + } + + pub fn weather_request_cloud_state( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + min_x: f32, + min_y: f32, + min_z: f32, + max_x: f32, + max_y: f32, + max_z: f32, + flags: DWORD, + ) -> bool { + unsafe { + SimConnect_WeatherRequestCloudState( + self.handle, request_id, min_x, min_y, min_z, max_x, max_y, max_z, flags, + ) == 0 + } + } + + pub fn weather_create_thermal( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, + radius: f32, + height: f32, + core_rate: f32, + core_turbulence: f32, + sink_rate: f32, + sink_turbulence: f32, + core_size: f32, + core_transition_size: f32, + sink_layer_size: f32, + sink_transition_size: f32, + ) -> bool { + unsafe { + SimConnect_WeatherCreateThermal( + self.handle, + request_id, + lat, + lon, + alt, + radius, + height, + core_rate, + core_turbulence, + sink_rate, + sink_turbulence, + core_size, + core_transition_size, + sink_layer_size, + sink_transition_size, + ) == 0 + } + } + + pub fn weather_remove_thermal(&self, object_id: SIMCONNECT_OBJECT_ID) -> bool { + unsafe { SimConnect_WeatherRemoveThermal(self.handle, object_id) == 0 } + } + + // ==================== Mission & System ==================== + + pub fn execute_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_ExecuteMissionAction(self.handle, instance_id) == 0 } + } + + pub fn complete_custom_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_CompleteCustomMissionAction(self.handle, instance_id) == 0 } + } + + pub fn request_system_state(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, state: &str) -> bool { + let state = cstring(state); + unsafe { SimConnect_RequestSystemState(self.handle, request_id, state.as_ptr()) == 0 } + } + + pub fn set_system_state(&self, state: &str, integer: DWORD, float_val: f32, string_val: &str) -> bool { + let state_c = cstring(state); + let string_c = cstring(string_val); + + unsafe { + SimConnect_SetSystemState( + self.handle, + state_c.as_ptr(), + integer, + float_val, + string_c.as_ptr(), + ) == 0 + } + } + + pub fn flight_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightLoad(self.handle, name.as_ptr()) == 0 } + } + + pub fn flight_save(&self, file_name: &str, title: &str, description: &str, flags: DWORD) -> bool { + let name = cstring(file_name); + let t = cstring(title); + let d = cstring(description); + unsafe { SimConnect_FlightSave(self.handle, name.as_ptr(), t.as_ptr(), d.as_ptr(), flags) == 0 } + } + + pub fn flight_plan_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightPlanLoad(self.handle, name.as_ptr()) == 0 } + } + + // ==================== Facilities ==================== + + pub fn subscribe_to_facilities( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_SubscribeToFacilities(self.handle, list_type, request_id) == 0 } + } + + pub fn unsubscribe_to_facilities(&self, list_type: SIMCONNECT_FACILITY_LIST_TYPE) -> bool { + unsafe { SimConnect_UnsubscribeToFacilities(self.handle, list_type) == 0 } + } + + pub fn request_facilities_list( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_RequestFacilitiesList(self.handle, list_type, request_id) == 0 } + } + + pub fn add_to_facility_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID, field_name: &str) -> bool { + let field = cstring(field_name); + unsafe { SimConnect_AddToFacilityDefinition(self.handle, define_id, field.as_ptr()) == 0 } + } + + pub fn request_facility_data( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + region: Option<&str>, + ) -> bool { + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); + unsafe { + SimConnect_RequestFacilityData( + self.handle, + define_id, + request_id, + icao.as_ptr(), + region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + ) == 0 + } + } + + pub fn subscribe_to_facilities_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + new_in_range_request_id: SIMCONNECT_DATA_REQUEST_ID, + old_out_of_range_request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { + SimConnect_SubscribeToFacilities_EX1( + self.handle, + list_type, + new_in_range_request_id, + old_out_of_range_request_id, + ) == 0 + } + } + + pub fn unsubscribe_to_facilities_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + unsubscribe_new_in_range: bool, + unsubscribe_old_out_of_range: bool, + ) -> bool { + unsafe { + SimConnect_UnsubscribeToFacilities_EX1( + self.handle, + list_type, + unsubscribe_new_in_range, + unsubscribe_old_out_of_range, + ) == 0 + } + } + + pub fn request_facilities_list_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { + SimConnect_RequestFacilitiesList_EX1(self.handle, list_type, request_id) == 0 + } + } + + pub fn request_facility_data_ex1( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + region: Option<&str>, + type_: Option, + ) -> bool { + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); + unsafe { + SimConnect_RequestFacilityData_EX1( + self.handle, + define_id, + request_id, + icao.as_ptr(), + region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + type_.unwrap_or(0) as ::std::os::raw::c_char, + ) == 0 + } + } + + pub unsafe fn request_jetway_data( + &self, + airport_icao: &str, + array_count: DWORD, + indexes: *mut i32, + ) -> bool { + let icao = cstring(airport_icao); + unsafe { + SimConnect_RequestJetwayData(self.handle, icao.as_ptr(), array_count, indexes) == 0 + } + } + + pub fn add_facility_data_definition_filter( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + filter_path: &str, + filter_data: *const std::os::raw::c_void, + cb_unit_size: DWORD, + ) -> bool { + let path = cstring(filter_path); + unsafe { + SimConnect_AddFacilityDataDefinitionFilter( + self.handle, + define_id, + path.as_ptr(), + cb_unit_size, + filter_data as *mut _, + ) == 0 + } + } + + pub fn clear_all_facility_data_definition_filters( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + ) -> bool { + unsafe { + SimConnect_ClearAllFacilityDataDefinitionFilters(self.handle, define_id) == 0 + } + } + + // ==================== Camera ==================== + + pub fn camera_set_relative_6dof( + &self, + delta_x: f32, + delta_y: f32, + delta_z: f32, + pitch: f32, + bank: f32, + heading: f32, + ) -> bool { + unsafe { + SimConnect_CameraSetRelative6DOF( + self.handle, delta_x, delta_y, delta_z, pitch, bank, heading, + ) == 0 + } + } + + // ==================== Menu ==================== + + pub fn menu_add_item( + &self, + menu_item: &str, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, + ) -> bool { + let item = cstring(menu_item); + unsafe { SimConnect_MenuAddItem(self.handle, item.as_ptr(), event_id, data) == 0 } + } + + pub fn menu_add_sub_item( + &self, + menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + menu_item: &str, + sub_menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, + ) -> bool { + let item = cstring(menu_item); + unsafe { + SimConnect_MenuAddSubItem(self.handle, menu_event_id, item.as_ptr(), sub_menu_event_id, data) == 0 + } + } + + pub fn menu_delete_item(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_MenuDeleteItem(self.handle, event_id) == 0 } + } + + pub fn menu_delete_sub_item( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + sub_event_id: SIMCONNECT_CLIENT_EVENT_ID, + ) -> bool { + unsafe { SimConnect_MenuDeleteSubItem(self.handle, event_id, sub_event_id) == 0 } + } + + // ==================== Other ==================== + + pub fn enumerate_controllers(&self) -> bool { + unsafe { SimConnect_EnumerateControllers(self.handle) == 0 } + } + + pub fn enumerate_input_events(&self, request_id: SIMCONNECT_DATA_REQUEST_ID) -> bool { + unsafe { SimConnect_EnumerateInputEvents(self.handle, request_id) == 0 } + } + + pub fn get_input_event(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, hash: u64) -> bool { + unsafe { SimConnect_GetInputEvent(self.handle, request_id, hash) == 0 } + } + + pub unsafe fn set_input_event( + &self, + hash: u64, + unit_size: DWORD, + value: *mut std::os::raw::c_void, + ) -> bool { + unsafe { SimConnect_SetInputEvent(self.handle, hash, unit_size, value) == 0 } + } + + pub fn subscribe_input_event(&self, hash: u64) -> bool { + unsafe { SimConnect_SubscribeInputEvent(self.handle, hash) == 0 } + } + + pub fn unsubscribe_input_event(&self, hash: u64) -> bool { + unsafe { SimConnect_UnsubscribeInputEvent(self.handle, hash) == 0 } + } + + pub fn enumerate_input_event_params(&self, hash: u64) -> bool { + unsafe { SimConnect_EnumerateInputEventParams(self.handle, hash) == 0 } + } + + pub unsafe fn execute_action( + &self, + request_id: DWORD, + action_id: &str, + unit_size: DWORD, + param_values: *mut std::os::raw::c_void, + ) -> bool { + let action = cstring(action_id); + unsafe { + SimConnect_ExecuteAction(self.handle, request_id, action.as_ptr(), unit_size, param_values) == 0 + } + } + + pub unsafe fn text( + &self, + text_type: SIMCONNECT_TEXT_TYPE, + time_in_seconds: f32, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + unit_size: DWORD, + data_set: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_Text(self.handle, text_type, time_in_seconds, event_id, unit_size, data_set) == 0 + } + } + + pub unsafe fn get_last_sent_packet_id(&self, error: *mut DWORD) -> bool { + unsafe { SimConnect_GetLastSentPacketID(self.handle, error) == 0 } + } + + pub unsafe fn call_dispatch( + &self, + dispatch_callback: DispatchProc, + context: *mut std::os::raw::c_void, + ) -> bool { + unsafe { SimConnect_CallDispatch(self.handle, dispatch_callback, context) == 0 } + } + + pub unsafe fn request_response_times(&self, count: DWORD, elapsed_seconds: *mut f32) -> bool { + unsafe { SimConnect_RequestResponseTimes(self.handle, count, elapsed_seconds) == 0 } + } + + // ==================== String Utilities ==================== + + pub unsafe fn retrieve_string( + p_data: *mut SIMCONNECT_RECV, + cb_data: DWORD, + p_string_v: *mut std::os::raw::c_void, + psz_string: *mut *mut std::os::raw::c_char, + pcb_string: *mut DWORD, + ) -> bool { + unsafe { + SimConnect_RetrieveString(p_data, cb_data, p_string_v, psz_string, pcb_string) == 0 + } + } + + pub unsafe fn insert_string( + p_dest: *mut std::os::raw::c_char, + cb_dest: DWORD, + pp_end: *mut *mut std::os::raw::c_void, + pcb_string: *mut DWORD, + p_source: *const std::os::raw::c_char, + ) -> bool { + unsafe { + SimConnect_InsertString(p_dest, cb_dest, pp_end, pcb_string, p_source) == 0 + } + } + + // ==================== Main Message Loop ==================== + + pub fn get_next_message(&self) -> Result, &str> { + unsafe { + let mut data_buf: *mut SIMCONNECT_RECV = ptr::null_mut(); + let mut size_buf: DWORD = 0; + + if SimConnect_GetNextDispatch(self.handle, &mut data_buf, &mut size_buf) != 0 { + return Err("Failed getting data from SimConnect"); + } + + if data_buf.is_null() { + return Ok(DispatchResult::Null); + } + + match (*data_buf).dwID as SIMCONNECT_RECV_ID { + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(DispatchResult::Null), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => Ok(DispatchResult::Exception(&*(data_buf as *const SIMCONNECT_RECV_EXCEPTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Ok(DispatchResult::Open(&*(data_buf as *const SIMCONNECT_RECV_OPEN))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Ok(DispatchResult::Quit(&*(data_buf as *const SIMCONNECT_RECV_QUIT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => Ok(DispatchResult::Event(&*(data_buf as *const SIMCONNECT_RECV_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE => Ok(DispatchResult::EventObjectAddRemove(&*(data_buf as *const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FILENAME => Ok(DispatchResult::EventFilename(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FILENAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FRAME => Ok(DispatchResult::EventFrame(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FRAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => Ok(DispatchResult::SimObjectData(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE => Ok(DispatchResult::SimObjectDataByType(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WEATHER_OBSERVATION => Ok(DispatchResult::WeatherObservation(&*(data_buf as *const SIMCONNECT_RECV_WEATHER_OBSERVATION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLOUD_STATE => Ok(DispatchResult::CloudState(&*(data_buf as *const SIMCONNECT_RECV_CLOUD_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID => Ok(DispatchResult::AssignedObjectId(&*(data_buf as *const SIMCONNECT_RECV_ASSIGNED_OBJECT_ID))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_RESERVED_KEY => Ok(DispatchResult::ReservedKey(&*(data_buf as *const SIMCONNECT_RECV_RESERVED_KEY))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CUSTOM_ACTION => Ok(DispatchResult::CustomAction(&*(data_buf as *const SIMCONNECT_RECV_CUSTOM_ACTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SYSTEM_STATE => Ok(DispatchResult::SystemState(&*(data_buf as *const SIMCONNECT_RECV_SYSTEM_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLIENT_DATA => Ok(DispatchResult::ClientData(&*(data_buf as *const SIMCONNECT_RECV_CLIENT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE => Ok(DispatchResult::EventWeatherMode(&*(data_buf as *const SIMCONNECT_RECV_EVENT_WEATHER_MODE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => Ok(DispatchResult::AirportList(&*(data_buf as *const SIMCONNECT_RECV_AIRPORT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_VOR_LIST => Ok(DispatchResult::VorList(&*(data_buf as *const SIMCONNECT_RECV_VOR_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NDB_LIST => Ok(DispatchResult::NdbList(&*(data_buf as *const SIMCONNECT_RECV_NDB_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WAYPOINT_LIST => Ok(DispatchResult::WaypointList(&*(data_buf as *const SIMCONNECT_RECV_WAYPOINT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED => Ok(DispatchResult::EventMultiplayerServerStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED => Ok(DispatchResult::EventMultiplayerClientStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED => Ok(DispatchResult::EventMultiplayerSessionEnded(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_END => Ok(DispatchResult::EventRaceEnd(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_LAP => Ok(DispatchResult::EventRaceLap(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_LAP))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_EX1 => Ok(DispatchResult::EventEx1(&*(data_buf as *const SIMCONNECT_RECV_EVENT_EX1))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA => Ok(DispatchResult::FacilityData(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA_END => Ok(DispatchResult::FacilityDataEnd(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST => Ok(DispatchResult::FacilityMinimalList(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_MINIMAL_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_JETWAY_DATA => Ok(DispatchResult::JetwayData(&*(data_buf as *const SIMCONNECT_RECV_JETWAY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ACTION_CALLBACK => Ok(DispatchResult::ActionCallback(&*(data_buf as *const SIMCONNECT_RECV_ACTION_CALLBACK))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS => Ok(DispatchResult::EnumerateInputEvents(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_GET_INPUT_EVENT => Ok(DispatchResult::GetInputEvent(&*(data_buf as *const SIMCONNECT_RECV_GET_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT => Ok(DispatchResult::SubscribeInputEvent(&*(data_buf as *const SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS => Ok(DispatchResult::EnumerateInputEventParams(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CONTROLLERS_LIST => Ok(DispatchResult::ControllersList(&*(data_buf as *const SIMCONNECT_RECV_CONTROLLERS_LIST))), + _ => Err("Unhandled RECV_ID"), + } + } + } +} + +impl Drop for SimConnector { + fn drop(&mut self) { + if !self.handle.is_null() { + let _ = self.close(); + } + } +} + +#[inline] +fn cstring(s: &str) -> CString { + CString::new(s).expect("string contained interior nul byte") +} diff --git a/simulators/FS2024/Cargo.toml b/simulators/FS2024/Cargo.toml new file mode 100644 index 0000000..78c459b --- /dev/null +++ b/simulators/FS2024/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "simconnect-fs2024" +license = "MIT" +description = "Rust bindings for SimConnect" +version = "0.5.0" +authors = ["Connor T"] +edition = "2021" + +[build-dependencies] +bindgen = "0.72" diff --git a/simulators/FS2024/SimConnect.dll b/simulators/FS2024/SimConnect.dll new file mode 100644 index 0000000000000000000000000000000000000000..8c4209c99f45ad3117bc88f9f28ba9a2be55bbea GIT binary patch literal 85504 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≤|(naUyY~r5EWH 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 literal 0 HcmV?d00001 diff --git a/simulators/FS2024/build.rs b/simulators/FS2024/build.rs new file mode 100644 index 0000000..a8ebde3 --- /dev/null +++ b/simulators/FS2024/build.rs @@ -0,0 +1,361 @@ +use std::{env, path::PathBuf}; + +fn main() { + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let lib_dir = PathBuf::from(manifest_dir).join("libsrc").join("lib"); + + println!("cargo:rustc-link-search={}", lib_dir.display()); + println!("cargo:rustc-link-lib=static=SimConnect"); + + let handle = std::thread::Builder::new() + .stack_size(128 * 1024 * 1024) + .spawn(|| { + let mut builder = bindgen::Builder::default() + .header("libsrc/include/SimConnect.hpp") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .impl_debug(true); + + // ==================== CONSTANTS / VARS ==================== + let vars = [ + "SIMCONNECT_UNUSED", + "SIMCONNECT_OBJECT_ID_USER", + "SIMCONNECT_OBJECT_ID_MAX", + "SIMCONNECT_OBJECT_ID_USER_AIRCRAFT", + "SIMCONNECT_OBJECT_ID_USER_AVATAR", + "SIMCONNECT_OBJECT_ID_USER_CURRENT", + "SIMCONNECT_CAMERA_IGNORE_FIELD", + "SIMCONNECT_CLIENTDATA_MAX_SIZE", + "SIMCONNECT_GROUP_PRIORITY_HIGHEST", + "SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE", + "SIMCONNECT_GROUP_PRIORITY_STANDARD", + "SIMCONNECT_GROUP_PRIORITY_DEFAULT", + "SIMCONNECT_GROUP_PRIORITY_LOWEST", + "MAX_METAR_LENGTH", + "MAX_THERMAL_SIZE", + "MAX_THERMAL_RATE", + "INITPOSITION_AIRSPEED_CRUISE", + "INITPOSITION_AIRSPEED_KEEP", + "SIMCONNECT_CLIENTDATATYPE_INT8", + "SIMCONNECT_CLIENTDATATYPE_INT16", + "SIMCONNECT_CLIENTDATATYPE_INT32", + "SIMCONNECT_CLIENTDATATYPE_INT64", + "SIMCONNECT_CLIENTDATATYPE_FLOAT32", + "SIMCONNECT_CLIENTDATATYPE_FLOAT64", + "SIMCONNECT_CLIENTDATAOFFSET_AUTO", + "SIMCONNECT_OPEN_CONFIGINDEX_LOCAL", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE", + "SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME", + "SIMCONNECT_WAYPOINT_NONE", + "SIMCONNECT_WAYPOINT_SPEED_REQUESTED", + "SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED", + "SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED", + "SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL", + "SIMCONNECT_WAYPOINT_ON_GROUND", + "SIMCONNECT_WAYPOINT_REVERSE", + "SIMCONNECT_WAYPOINT_WRAP_TO_FIRST", + "SIMCONNECT_WAYPOINT_ALWAYS_BACKUP", + "SIMCONNECT_WAYPOINT_KEEP_LAST_HEADING", + "SIMCONNECT_WAYPOINT_YIELD_TO_USER", + "SIMCONNECT_WAYPOINT_CAN_REVERSE", + "SIMCONNECT_EVENT_FLAG_DEFAULT", + "SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER", + "SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER", + "SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY", + "SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT", + "SIMCONNECT_DATA_REQUEST_FLAG_CHANGED", + "SIMCONNECT_DATA_REQUEST_FLAG_TAGGED", + "SIMCONNECT_DATA_SET_FLAG_DEFAULT", + "SIMCONNECT_DATA_SET_FLAG_TAGGED", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED", + "SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT", + "SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL", + "SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER", + "UNKNOWN_SENDID", + "UNKNOWN_INDEX", + "UNKNOWN_GROUP", + "SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH", + "SIMCONNECT_CLOUD_STATE_ARRAY_SIZE", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_JS", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_WASM", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT_SELF_CALL", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_DEFAULT", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_ALL_SIMCONNECT", + "SIMCONNECT_COMM_BUS_BROADCAST_TO_ALL", + "SIMCONNECT_CAMERA_DATA_MASK_NONE", + "SIMCONNECT_CAMERA_DATA_MASK_POSITION", + "SIMCONNECT_CAMERA_DATA_MASK_ROTATION", + "SIMCONNECT_CAMERA_DATA_MASK_TARGETED", + "SIMCONNECT_CAMERA_DATA_MASK_FOV", + "SIMCONNECT_CAMERA_DATA_MASK_ALL_ROTATION", + "SIMCONNECT_CAMERA_DATA_MASK_ALL_TARGETED", + "SIMCONNECT_CAMERA_FLAG_INTERACTION", + "SIMCONNECT_CAMERA_FLAG_ABOVE_GROUND", + ]; + + for v in vars { + builder = builder.allowlist_var(v); + } + + // ==================== TYPES / ENUMS ==================== + let types = [ + "HANDLE", + "SIMCONNECT_RECV_ID", + "SIMCONNECT_DATATYPE", + "SIMCONNECT_EXCEPTION", + "SIMCONNECT_SIMOBJECT_TYPE", + "SIMCONNECT_STATE", + "SIMCONNECT_PERIOD", + "SIMCONNECT_MISSION_END", + "SIMCONNECT_CLIENT_DATA_PERIOD", + "SIMCONNECT_TEXT_TYPE", + "SIMCONNECT_TEXT_RESULT", + "SIMCONNECT_WEATHER_MODE", + "SIMCONNECT_FACILITY_LIST_TYPE", + "SIMCONNECT_FACILITY_DATA_TYPE", + "SIMCONNECT_INPUT_EVENT_TYPE", + "SIMCONNECT_VOR_FLAGS", + "SIMCONNECT_WAYPOINT_FLAGS", + "SIMCONNECT_EVENT_FLAG", + "SIMCONNECT_DATA_REQUEST_FLAG", + "SIMCONNECT_DATA_SET_FLAG", + "SIMCONNECT_CREATE_CLIENT_DATA_FLAG", + "SIMCONNECT_CLIENT_DATA_REQUEST_FLAG", + "SIMCONNECT_CLIENT_DATA_SET_FLAG", + "SIMCONNECT_VIEW_SYSTEM_EVENT_DATA", + "SIMCONNECT_SOUND_SYSTEM_EVENT_DATA", + "SIMCONNECT_FLOW_EVENT", + "SIMCONNECT_POSITION_REFERENTIAL", + "SIMCONNECT_COMM_BUS_BROADCAST_TO", + "SIMCONNECT_CAMERA_DATA_MASK", + "SIMCONNECT_CAMERA_FLAG", + "SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS", + "SIMCONNECT_CAMERA_AVAILABILITY", + ]; + + for t in types { + builder = builder.allowlist_type(t); + } + + // ==================== STRUCTS ==================== + let structs = [ + "SIMCONNECT_RECV", + "SIMCONNECT_RECV_EXCEPTION", + "SIMCONNECT_RECV_OPEN", + "SIMCONNECT_RECV_QUIT", + "SIMCONNECT_RECV_EVENT", + "SIMCONNECT_RECV_EVENT_FILENAME", + "SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE", + "SIMCONNECT_RECV_EVENT_FRAME", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED", + "SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED", + "SIMCONNECT_RECV_EVENT_RACE_END", + "SIMCONNECT_RECV_EVENT_RACE_LAP", + "SIMCONNECT_RECV_SIMOBJECT_DATA", + "SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE", + "SIMCONNECT_RECV_CLIENT_DATA", + "SIMCONNECT_RECV_WEATHER_OBSERVATION", + "SIMCONNECT_RECV_CLOUD_STATE", + "SIMCONNECT_RECV_ASSIGNED_OBJECT_ID", + "SIMCONNECT_RECV_RESERVED_KEY", + "SIMCONNECT_RECV_SYSTEM_STATE", + "SIMCONNECT_RECV_CUSTOM_ACTION", + "SIMCONNECT_RECV_EVENT_WEATHER_MODE", + "SIMCONNECT_RECV_FACILITIES_LIST", + "SIMCONNECT_DATA_FACILITY_AIRPORT", + "SIMCONNECT_RECV_AIRPORT_LIST", + "SIMCONNECT_DATA_FACILITY_WAYPOINT", + "SIMCONNECT_RECV_WAYPOINT_LIST", + "SIMCONNECT_DATA_FACILITY_NDB", + "SIMCONNECT_RECV_NDB_LIST", + "SIMCONNECT_DATA_FACILITY_VOR", + "SIMCONNECT_RECV_VOR_LIST", + "SIMCONNECT_RECV_EVENT_EX1", + "SIMCONNECT_DATA_RACE_RESULT", + "SIMCONNECT_RECV_FACILITY_DATA", + "SIMCONNECT_RECV_FACILITY_DATA_END", + "SIMCONNECT_ICAO", + "SIMCONNECT_FACILITY_MINIMAL", + "SIMCONNECT_RECV_FACILITY_MINIMAL_LIST", + "SIMCONNECT_DATA_PBH", + "SIMCONNECT_JETWAY_DATA", + "SIMCONNECT_RECV_JETWAY_DATA", + "SIMCONNECT_RECV_ACTION_CALLBACK", + "SIMCONNECT_INPUT_EVENT_DESCRIPTOR", + "SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS", + "SIMCONNECT_RECV_GET_INPUT_EVENT", + "SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT", + "SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS", + "SIMCONNECT_VERSION_BASE_TYPE", + "SIMCONNECT_CONTROLLER_ITEM", + "SIMCONNECT_RECV_CONTROLLERS_LIST", + "SIMCONNECT_RECV_LIST_TEMPLATE", + "SIMCONNECT_DATA_INITPOSITION", + "SIMCONNECT_DATA_MARKERSTATE", + "SIMCONNECT_DATA_WAYPOINT", + "SIMCONNECT_DATA_LATLONALT", + "SIMCONNECT_DATA_XYZ", + "SIMCONNECT_DATA_CAMERA", + "SIMCONNECT_RECV_CAMERA_DATA", + "SIMCONNECT_RECV_CAMERA_WORLD_LOCKER", + "SIMCONNECT_RECV_CAMERA_STATUS", + "SIMCONNECT_ENUMERATE_SIMOBJECT_LIVERY", + "SIMCONNECT_RECV_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST", + "SIMCONNECT_RECV_FLOW_EVENT", + "SIMCONNECT_CAMERA_DEFINITION_ITEM", + "SIMCONNECT_RECV_CAMERA_DEFINITION_LIST", + "SIMCONNECT_RECV_COMM_BUS", + ]; + + for s in structs { + builder = builder.allowlist_type(s); + } + + // ==================== FUNCTIONS ==================== + let functions = [ + "SimConnect_MapClientEventToSimEvent", + "SimConnect_TransmitClientEvent", + "SimConnect_SetSystemEventState", + "SimConnect_AddClientEventToNotificationGroup", + "SimConnect_RemoveClientEvent", + "SimConnect_SetNotificationGroupPriority", + "SimConnect_ClearNotificationGroup", + "SimConnect_RequestNotificationGroup", + "SimConnect_AddToDataDefinition", + "SimConnect_ClearDataDefinition", + "SimConnect_RequestDataOnSimObject", + "SimConnect_RequestDataOnSimObjectType", + "SimConnect_SetDataOnSimObject", + "SimConnect_MapInputEventToClientEvent", + "SimConnect_SetInputGroupPriority", + "SimConnect_RemoveInputEvent", + "SimConnect_ClearInputGroup", + "SimConnect_SetInputGroupState", + "SimConnect_RequestReservedKey", + "SimConnect_SubscribeToSystemEvent", + "SimConnect_UnsubscribeFromSystemEvent", + "SimConnect_WeatherRequestInterpolatedObservation", + "SimConnect_WeatherRequestObservationAtStation", + "SimConnect_WeatherRequestObservationAtNearestStation", + "SimConnect_WeatherCreateStation", + "SimConnect_WeatherRemoveStation", + "SimConnect_WeatherSetObservation", + "SimConnect_WeatherSetModeServer", + "SimConnect_WeatherSetModeTheme", + "SimConnect_WeatherSetModeGlobal", + "SimConnect_WeatherSetModeCustom", + "SimConnect_WeatherSetDynamicUpdateRate", + "SimConnect_WeatherRequestCloudState", + "SimConnect_WeatherCreateThermal", + "SimConnect_WeatherRemoveThermal", + "SimConnect_AICreateParkedATCAircraft", + "SimConnect_AICreateEnrouteATCAircraft", + "SimConnect_AICreateNonATCAircraft", + "SimConnect_AICreateSimulatedObject", + "SimConnect_AIReleaseControl", + "SimConnect_AIRemoveObject", + "SimConnect_AISetAircraftFlightPlan", + "SimConnect_ExecuteMissionAction", + "SimConnect_CompleteCustomMissionAction", + "SimConnect_Close", + "SimConnect_RetrieveString", + "SimConnect_GetLastSentPacketID", + "SimConnect_Open", + "SimConnect_CallDispatch", + "SimConnect_GetNextDispatch", + "SimConnect_RequestResponseTimes", + "SimConnect_InsertString", + "SimConnect_CameraSetRelative6DOF", + "SimConnect_MenuAddItem", + "SimConnect_MenuDeleteItem", + "SimConnect_MenuAddSubItem", + "SimConnect_MenuDeleteSubItem", + "SimConnect_RequestSystemState", + "SimConnect_SetSystemState", + "SimConnect_MapClientDataNameToID", + "SimConnect_CreateClientData", + "SimConnect_AddToClientDataDefinition", + "SimConnect_ClearClientDataDefinition", + "SimConnect_RequestClientData", + "SimConnect_SetClientData", + "SimConnect_FlightLoad", + "SimConnect_FlightSave", + "SimConnect_FlightPlanLoad", + "SimConnect_Text", + "SimConnect_SubscribeToFacilities", + "SimConnect_UnsubscribeToFacilities", + "SimConnect_RequestFacilitiesList", + "SimConnect_TransmitClientEvent_EX1", + "SimConnect_AddToFacilityDefinition", + "SimConnect_RequestFacilityData", + "SimConnect_SubscribeToFacilities_EX1", + "SimConnect_UnsubscribeToFacilities_EX1", + "SimConnect_RequestFacilitiesList_EX1", + "SimConnect_RequestFacilityData_EX1", + "SimConnect_RequestJetwayData", + "SimConnect_EnumerateControllers", + "SimConnect_MapInputEventToClientEvent_EX1", + "SimConnect_ExecuteAction", + "SimConnect_EnumerateInputEvents", + "SimConnect_GetInputEvent", + "SimConnect_SetInputEvent", + "SimConnect_SubscribeInputEvent", + "SimConnect_UnsubscribeInputEvent", + "SimConnect_EnumerateInputEventParams", + "SimConnect_AddFacilityDataDefinitionFilter", + "SimConnect_ClearAllFacilityDataDefinitionFilters", + "SimConnect_AICreateParkedATCAircraft_EX1", + "SimConnect_AICreateEnrouteATCAircraft_EX1", + "SimConnect_AICreateNonATCAircraft_EX1", + "SimConnect_AICreateSimulatedObject_EX1", + "SimConnect_EnumerateSimObjectsAndLiveries", + "SimConnect_SubscribeToFlowEvent", + "SimConnect_UnsubscribeToFlowEvent", + "SimConnect_RequestAllFacilities", + "SimConnect_CameraAcquire", + "SimConnect_CameraRelease", + "SimConnect_CameraGetStatus", + "SimConnect_CameraSet", + "SimConnect_CameraGet", + "SimConnect_CameraEnableFlag", + "SimConnect_CameraDisableFlag", + "SimConnect_SubscribeToCameraStatusUpdate", + "SimConnect_UnsubscribeToCameraStatusUpdate", + "SimConnect_EnumerateCameraDefinitions", + "SimConnect_CameraSetUsingCameraDefinition", + "SimConnect_SubscribeToCommBusEvent", + "SimConnect_UnsubscribeToCommBusEvent", + "SimConnect_CallCommBusEvent", + "SimConnect_SubscribeToCameraWorldLockerStatusUpdate", + "SimConnect_UnsubscribeToCameraWorldLockerStatusUpdate", + "SimConnect_RequestCameraWorldLocker", + "SimConnect_DeleteCameraWorldLocker", + ]; + + for f in functions { + builder = builder.allowlist_function(f); + } + + let bindings = builder + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); + }) + .expect("Failed to spawn bindgen thread"); + + handle.join().expect("Bindgen thread panicked"); +} diff --git a/simulators/FS2024/libsrc/include/SimConnect.hpp b/simulators/FS2024/libsrc/include/SimConnect.hpp new file mode 100644 index 0000000..1aeea8e --- /dev/null +++ b/simulators/FS2024/libsrc/include/SimConnect.hpp @@ -0,0 +1,1160 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +// Updated per FS2024 SDK 1.6.9 + +#pragma once + +#include + +#ifndef _SIMCONNECT_H_ +#define _SIMCONNECT_H_ + +#ifdef _MSFS_WASM + #ifndef SIMCONNECT_WASM_MODULE + #define SIMCONNECT_WASM_MODULE "env" + #endif +#endif + +#ifndef DWORD_MAX +#define DWORD_MAX 0xFFFFFFFF +#endif + +#include + +typedef DWORD SIMCONNECT_OBJECT_ID; + +//---------------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------------- + +static const DWORD SIMCONNECT_UNUSED = DWORD_MAX; // special value to indicate unused event, ID +static const DWORD SIMCONNECT_OBJECT_ID_MAX = DWORD_MAX - 128; // proxy value for User vehicle ObjectID +static const DWORD SIMCONNECT_OBJECT_ID_USER = 0; // deprecated - proxy legacy value for User aircraft ObjectID +static const DWORD SIMCONNECT_OBJECT_ID_USER_AIRCRAFT = 0; // proxy value for User aircraft ObjectID +static const DWORD SIMCONNECT_OBJECT_ID_USER_AVATAR = SIMCONNECT_OBJECT_ID_MAX + 1; // proxy value for User avatar ObjectID +static const DWORD SIMCONNECT_OBJECT_ID_USER_CURRENT = SIMCONNECT_OBJECT_ID_MAX + 2; // proxy value for User aircraft/avatar ObjectID + +static const float SIMCONNECT_CAMERA_IGNORE_FIELD = FLT_MAX; //Used to tell the Camera API to NOT modify the value in this part of the argument. + +static const DWORD SIMCONNECT_CLIENTDATA_MAX_SIZE = 8192; // maximum value for SimConnect_CreateClientData dwSize parameter + + +// Notification Group priority values +static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000; // highest priority that allows events to be masked +static const DWORD SIMCONNECT_GROUP_PRIORITY_STANDARD = 1900000000; // standard priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_DEFAULT = 2000000000; // default priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_LOWEST = 4000000000; // priorities lower than this will be ignored + +//Weather observations Metar strings +static const DWORD MAX_METAR_LENGTH = 2000; + +// Maximum thermal size is 100 km. +static const float MAX_THERMAL_SIZE = 100000; +static const float MAX_THERMAL_RATE = 1000; + +// SIMCONNECT_DATA_INITPOSITION.Airspeed +static const DWORD INITPOSITION_AIRSPEED_CRUISE = -1; // aircraft's cruise airspeed +static const DWORD INITPOSITION_AIRSPEED_KEEP = -2; // keep current airspeed + +// AddToClientDataDefinition dwSizeOrType parameter type values +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT8 = -1; // 8-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT16 = -2; // 16-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT32 = -3; // 32-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT64 = -4; // 64-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT32 = -5; // 32-bit floating-point number (float) +static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT64 = -6; // 64-bit floating-point number (double) + +// AddToClientDataDefinition dwOffset parameter special values +static const DWORD SIMCONNECT_CLIENTDATAOFFSET_AUTO = -1; // automatically compute offset of the ClientData variable + +// Open ConfigIndex parameter special value +static const DWORD SIMCONNECT_OPEN_CONFIGINDEX_LOCAL = -1; // ignore SimConnect.cfg settings, and force local connection + +//---------------------------------------------------------------------------- +// Enum definitions +//---------------------------------------------------------------------------- + +//these came from substituteMacros +#define SIMCONNECT_REFSTRUCT struct +#define SIMCONNECT_STRUCT struct +#define SIMCONNECT_STRING(name, size) char name[size] +#define SIMCONNECT_GUID GUID +#define SIMCONNECT_STRINGV(name) char name[1] +#define SIMCONNECT_DATAV(name, id, count) DWORD name +#define SIMCONNECT_FIXEDTYPE_DATAV(type, name, count, cliMarshalAs, cliType) type name[1] +#define SIMCONNECT_GUID GUID +#define SIMCONNECT_ENUM enum +#define SIMCONNECT_ENUM_FLAGS typedef DWORD +#define SIMCONNECT_USER_ENUM typedef DWORD +#define SIMCONNECT_TYPEDEF(type, new_type) typedef type new_type; + +// Receive data types +SIMCONNECT_ENUM SIMCONNECT_RECV_ID +{ + SIMCONNECT_RECV_ID_NULL, + SIMCONNECT_RECV_ID_EXCEPTION, + SIMCONNECT_RECV_ID_OPEN, + SIMCONNECT_RECV_ID_QUIT, + SIMCONNECT_RECV_ID_EVENT, + SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE, + SIMCONNECT_RECV_ID_EVENT_FILENAME, + SIMCONNECT_RECV_ID_EVENT_FRAME, + SIMCONNECT_RECV_ID_SIMOBJECT_DATA, + SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE, + SIMCONNECT_RECV_ID_WEATHER_OBSERVATION, + SIMCONNECT_RECV_ID_CLOUD_STATE, + SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID, + SIMCONNECT_RECV_ID_RESERVED_KEY, + SIMCONNECT_RECV_ID_CUSTOM_ACTION, + SIMCONNECT_RECV_ID_SYSTEM_STATE, + SIMCONNECT_RECV_ID_CLIENT_DATA, + SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE, + SIMCONNECT_RECV_ID_AIRPORT_LIST, + SIMCONNECT_RECV_ID_VOR_LIST, + SIMCONNECT_RECV_ID_NDB_LIST, + SIMCONNECT_RECV_ID_WAYPOINT_LIST, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED, + SIMCONNECT_RECV_ID_EVENT_RACE_END, + SIMCONNECT_RECV_ID_EVENT_RACE_LAP, + SIMCONNECT_RECV_ID_EVENT_EX1, + SIMCONNECT_RECV_ID_FACILITY_DATA, + SIMCONNECT_RECV_ID_FACILITY_DATA_END, + SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST, + SIMCONNECT_RECV_ID_JETWAY_DATA, + SIMCONNECT_RECV_ID_CONTROLLERS_LIST, + SIMCONNECT_RECV_ID_ACTION_CALLBACK, + SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS, + SIMCONNECT_RECV_ID_GET_INPUT_EVENT, + SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT, + SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS, + SIMCONNECT_RECV_ID_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST, + SIMCONNECT_RECV_ID_FLOW_EVENT, + SIMCONNECT_RECV_ID_CAMERA_DATA, + SIMCONNECT_RECV_ID_CAMERA_STATUS, + SIMCONNECT_RECV_ID_CAMERA_DEFINITION_LIST, + SIMCONNECT_RECV_ID_COMM_BUS, + SIMCONNECT_RECV_ID_CAMERA_WORLD_LOCKER, +}; + +// Data data types +SIMCONNECT_ENUM SIMCONNECT_DATATYPE:int +{ + SIMCONNECT_DATATYPE_INVALID, // invalid data type + SIMCONNECT_DATATYPE_INT32, // 32-bit integer number + SIMCONNECT_DATATYPE_INT64, // 64-bit integer number + SIMCONNECT_DATATYPE_FLOAT32, // 32-bit floating-point number (float) + SIMCONNECT_DATATYPE_FLOAT64, // 64-bit floating-point number (double) + SIMCONNECT_DATATYPE_STRING8, // 8-byte string + SIMCONNECT_DATATYPE_STRING32, // 32-byte string + SIMCONNECT_DATATYPE_STRING64, // 64-byte string + SIMCONNECT_DATATYPE_STRING128, // 128-byte string + SIMCONNECT_DATATYPE_STRING256, // 256-byte string + SIMCONNECT_DATATYPE_STRING260, // 260-byte string + SIMCONNECT_DATATYPE_STRINGV, // variable-length string + SIMCONNECT_DATATYPE_INITPOSITION, // see SIMCONNECT_DATA_INITPOSITION + SIMCONNECT_DATATYPE_MARKERSTATE, // see SIMCONNECT_DATA_MARKERSTATE + SIMCONNECT_DATATYPE_WAYPOINT, // see SIMCONNECT_DATA_WAYPOINT + SIMCONNECT_DATATYPE_LATLONALT, // see SIMCONNECT_DATA_LATLONALT + SIMCONNECT_DATATYPE_XYZ, // see SIMCONNECT_DATA_XYZ + SIMCONNECT_DATATYPE_INT8, // 8-bit integer number, char + + SIMCONNECT_DATATYPE_MAX // enum limit +}; + +// Exception error types +SIMCONNECT_ENUM SIMCONNECT_EXCEPTION +{ + SIMCONNECT_EXCEPTION_NONE, + + SIMCONNECT_EXCEPTION_ERROR, + SIMCONNECT_EXCEPTION_SIZE_MISMATCH, + SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, + SIMCONNECT_EXCEPTION_UNOPENED, + SIMCONNECT_EXCEPTION_VERSION_MISMATCH, + SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, + SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, + SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, + SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, + SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, + SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, + SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, + SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, + SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, + SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, + SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, + SIMCONNECT_EXCEPTION_DATA_ERROR, + SIMCONNECT_EXCEPTION_INVALID_ARRAY, + SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, + SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED, + SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, + SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, + SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, + SIMCONNECT_EXCEPTION_INVALID_ENUM, + SIMCONNECT_EXCEPTION_DEFINITION_ERROR, + SIMCONNECT_EXCEPTION_DUPLICATE_ID, + SIMCONNECT_EXCEPTION_DATUM_ID, + SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, + SIMCONNECT_EXCEPTION_ALREADY_CREATED, + SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE, + SIMCONNECT_EXCEPTION_OBJECT_CONTAINER, + SIMCONNECT_EXCEPTION_OBJECT_AI, + SIMCONNECT_EXCEPTION_OBJECT_ATC, + SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE, + SIMCONNECT_EXCEPTION_JETWAY_DATA, + SIMCONNECT_EXCEPTION_ACTION_NOT_FOUND, + SIMCONNECT_EXCEPTION_NOT_AN_ACTION, + SIMCONNECT_EXCEPTION_INCORRECT_ACTION_PARAMS, + SIMCONNECT_EXCEPTION_GET_INPUT_EVENT_FAILED, + SIMCONNECT_EXCEPTION_SET_INPUT_EVENT_FAILED, + SIMCONNECT_EXCEPTION_EVENT_NAME_RESERVED, + SIMCONNECT_EXCEPTION_INTERNAL, + SIMCONNECT_EXCEPTION_CAMERA_API, +}; + +// Object types +SIMCONNECT_ENUM SIMCONNECT_SIMOBJECT_TYPE +{ + SIMCONNECT_SIMOBJECT_TYPE_USER = 0, + SIMCONNECT_SIMOBJECT_TYPE_USER_AIRCRAFT = 0, + SIMCONNECT_SIMOBJECT_TYPE_ALL, + SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, + SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER, + SIMCONNECT_SIMOBJECT_TYPE_BOAT, + SIMCONNECT_SIMOBJECT_TYPE_GROUND, + SIMCONNECT_SIMOBJECT_TYPE_HOT_AIR_BALLOON, + SIMCONNECT_SIMOBJECT_TYPE_ANIMAL, + SIMCONNECT_SIMOBJECT_TYPE_USER_AVATAR, + SIMCONNECT_SIMOBJECT_TYPE_USER_CURRENT, +}; + +// EventState values +SIMCONNECT_ENUM SIMCONNECT_STATE +{ + SIMCONNECT_STATE_OFF, + SIMCONNECT_STATE_ON, +}; + +// Object Data Request Period values +SIMCONNECT_ENUM SIMCONNECT_PERIOD +{ + SIMCONNECT_PERIOD_NEVER, + SIMCONNECT_PERIOD_ONCE, + SIMCONNECT_PERIOD_VISUAL_FRAME, + SIMCONNECT_PERIOD_SIM_FRAME, + SIMCONNECT_PERIOD_SECOND, +}; + +SIMCONNECT_ENUM SIMCONNECT_MISSION_END +{ + SIMCONNECT_MISSION_FAILED, + SIMCONNECT_MISSION_CRASHED, + SIMCONNECT_MISSION_SUCCEEDED +}; + +// ClientData Request Period values +SIMCONNECT_ENUM SIMCONNECT_CLIENT_DATA_PERIOD +{ + SIMCONNECT_CLIENT_DATA_PERIOD_NEVER, + SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, + SIMCONNECT_CLIENT_DATA_PERIOD_VISUAL_FRAME, + SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, + SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, +}; + +SIMCONNECT_ENUM SIMCONNECT_TEXT_TYPE +{ + SIMCONNECT_TEXT_TYPE_SCROLL_BLACK, + SIMCONNECT_TEXT_TYPE_SCROLL_WHITE, + SIMCONNECT_TEXT_TYPE_SCROLL_RED, + SIMCONNECT_TEXT_TYPE_SCROLL_GREEN, + SIMCONNECT_TEXT_TYPE_SCROLL_BLUE, + SIMCONNECT_TEXT_TYPE_SCROLL_YELLOW, + SIMCONNECT_TEXT_TYPE_SCROLL_MAGENTA, + SIMCONNECT_TEXT_TYPE_SCROLL_CYAN, + SIMCONNECT_TEXT_TYPE_PRINT_BLACK = 0x0100, + SIMCONNECT_TEXT_TYPE_PRINT_WHITE, + SIMCONNECT_TEXT_TYPE_PRINT_RED, + SIMCONNECT_TEXT_TYPE_PRINT_GREEN, + SIMCONNECT_TEXT_TYPE_PRINT_BLUE, + SIMCONNECT_TEXT_TYPE_PRINT_YELLOW, + SIMCONNECT_TEXT_TYPE_PRINT_MAGENTA, + SIMCONNECT_TEXT_TYPE_PRINT_CYAN, + SIMCONNECT_TEXT_TYPE_MENU = 0x0200, +}; + +SIMCONNECT_ENUM SIMCONNECT_TEXT_RESULT +{ + SIMCONNECT_TEXT_RESULT_MENU_SELECT_1, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_2, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_3, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_4, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_5, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_6, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_7, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_8, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_9, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_10, + SIMCONNECT_TEXT_RESULT_DISPLAYED = 0x00010000, + SIMCONNECT_TEXT_RESULT_QUEUED, + SIMCONNECT_TEXT_RESULT_REMOVED, + SIMCONNECT_TEXT_RESULT_REPLACED, + SIMCONNECT_TEXT_RESULT_TIMEOUT, +}; + +SIMCONNECT_ENUM SIMCONNECT_WEATHER_MODE +{ + SIMCONNECT_WEATHER_MODE_THEME, + SIMCONNECT_WEATHER_MODE_RWW, + SIMCONNECT_WEATHER_MODE_CUSTOM, + SIMCONNECT_WEATHER_MODE_GLOBAL, +}; + +SIMCONNECT_ENUM SIMCONNECT_FACILITY_LIST_TYPE +{ + SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, + SIMCONNECT_FACILITY_LIST_TYPE_WAYPOINT, + SIMCONNECT_FACILITY_LIST_TYPE_NDB, + SIMCONNECT_FACILITY_LIST_TYPE_VOR, + SIMCONNECT_FACILITY_LIST_TYPE_COUNT // invalid +}; + +SIMCONNECT_ENUM SIMCONNECT_FACILITY_DATA_TYPE +{ + SIMCONNECT_FACILITY_DATA_AIRPORT, + SIMCONNECT_FACILITY_DATA_RUNWAY, + SIMCONNECT_FACILITY_DATA_START, + SIMCONNECT_FACILITY_DATA_FREQUENCY, + SIMCONNECT_FACILITY_DATA_HELIPAD, + SIMCONNECT_FACILITY_DATA_APPROACH, + SIMCONNECT_FACILITY_DATA_APPROACH_TRANSITION, + SIMCONNECT_FACILITY_DATA_APPROACH_LEG, + SIMCONNECT_FACILITY_DATA_FINAL_APPROACH_LEG, + SIMCONNECT_FACILITY_DATA_MISSED_APPROACH_LEG, + SIMCONNECT_FACILITY_DATA_DEPARTURE, + SIMCONNECT_FACILITY_DATA_ARRIVAL, + SIMCONNECT_FACILITY_DATA_RUNWAY_TRANSITION, + SIMCONNECT_FACILITY_DATA_ENROUTE_TRANSITION, + SIMCONNECT_FACILITY_DATA_TAXI_POINT, + SIMCONNECT_FACILITY_DATA_TAXI_PARKING, + SIMCONNECT_FACILITY_DATA_TAXI_PATH, + SIMCONNECT_FACILITY_DATA_TAXI_NAME, + SIMCONNECT_FACILITY_DATA_JETWAY, + SIMCONNECT_FACILITY_DATA_VOR, + SIMCONNECT_FACILITY_DATA_NDB, + SIMCONNECT_FACILITY_DATA_WAYPOINT, + SIMCONNECT_FACILITY_DATA_ROUTE, + SIMCONNECT_FACILITY_DATA_PAVEMENT, + SIMCONNECT_FACILITY_DATA_APPROACH_LIGHTS, + SIMCONNECT_FACILITY_DATA_VASI, + SIMCONNECT_FACILITY_DATA_VDGS, + SIMCONNECT_FACILITY_DATA_HOLDING_PATTERN, + SIMCONNECT_FACILITY_DATA_TAXI_PARKING_AIRLINE, +}; + +SIMCONNECT_ENUM SIMCONNECT_INPUT_EVENT_TYPE : DWORD +{ + SIMCONNECT_INPUT_EVENT_TYPE_DOUBLE, + SIMCONNECT_INPUT_EVENT_TYPE_STRING +}; + +SIMCONNECT_ENUM SIMCONNECT_FLOW_EVENT : DWORD +{ + SIMCONNECT_FLOW_EVENT_NONE, + SIMCONNECT_FLOW_EVENT_FLT_LOAD, + SIMCONNECT_FLOW_EVENT_FLT_LOADED, + SIMCONNECT_FLOW_EVENT_TELEPORT_START, + SIMCONNECT_FLOW_EVENT_TELEPORT_DONE, + SIMCONNECT_FLOW_EVENT_BACK_ON_TRACK_START, + SIMCONNECT_FLOW_EVENT_BACK_ON_TRACK_DONE, + SIMCONNECT_FLOW_EVENT_SKIP_START, + SIMCONNECT_FLOW_EVENT_SKIP_DONE, + SIMCONNECT_FLOW_EVENT_BACK_TO_MAIN_MENU, + SIMCONNECT_FLOW_EVENT_RTC_START, + SIMCONNECT_FLOW_EVENT_RTC_END, + SIMCONNECT_FLOW_EVENT_REPLAY_START, + SIMCONNECT_FLOW_EVENT_REPLAY_END, + SIMCONNECT_FLOW_EVENT_FLIGHT_START, + SIMCONNECT_FLOW_EVENT_FLIGHT_END, + SIMCONNECT_FLOW_EVENT_PLANE_CRASH, +}; + + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_VOR_FLAGS; // flags for SIMCONNECT_RECV_ID_VOR_LIST + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL = 0x00000001; // Has Nav signal + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER = 0x00000002; // Has localizer + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE = 0x00000004; // Has Nav signal + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME = 0x00000008; // Station has DME + +// bits for the Waypoint Flags field: may be combined +SIMCONNECT_ENUM_FLAGS SIMCONNECT_WAYPOINT_FLAGS; + static const DWORD SIMCONNECT_WAYPOINT_NONE = 0x00; + static const DWORD SIMCONNECT_WAYPOINT_SPEED_REQUESTED = 0x04; // requested speed at waypoint is valid + static const DWORD SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED = 0x08; // request a specific throttle percentage + static const DWORD SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10; // compute vertical to speed to reach waypoint altitude when crossing the waypoint + static const DWORD SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL = 0x20; // AltitudeIsAGL + static const DWORD SIMCONNECT_WAYPOINT_ON_GROUND = 0x00100000; // place this waypoint on the ground + static const DWORD SIMCONNECT_WAYPOINT_REVERSE = 0x00200000; // Back up to this waypoint. Only valid on first waypoint + static const DWORD SIMCONNECT_WAYPOINT_WRAP_TO_FIRST = 0x00400000; // Wrap around back to first waypoint. Only valid on last waypoint. + static const DWORD SIMCONNECT_WAYPOINT_ALWAYS_BACKUP = 0x00800000; // Go from first waypoint to last one moving only backwards + static const DWORD SIMCONNECT_WAYPOINT_KEEP_LAST_HEADING = 0x01000000; // Object doesn't only go from waypoint to waypoint using position but it will also keep the same heading computed on the last 2 waypoints + static const DWORD SIMCONNECT_WAYPOINT_YIELD_TO_USER = 0x02000000; // Object will never be too close of the player. If waypoints pass too close of the player, the object will stop and wait + static const DWORD SIMCONNECT_WAYPOINT_CAN_REVERSE = 0x04000000; // This flags handle the behaviour of the object if it can't reach a waypoint. By default, it will take a other way and try to reach this point again. With this flag, object will try some stuff to reach this waypoint in a better condition (moving backwards...) + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_EVENT_FLAG; + static const DWORD SIMCONNECT_EVENT_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001; // set event repeat timer to simulate fast repeat + static const DWORD SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002; // set event repeat timer to simulate slow repeat + static const DWORD SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010; // interpret GroupID parameter as priority value + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_REQUEST_FLAG; + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested data when value(s) change + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested data in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_SET_FLAG; + static const DWORD SIMCONNECT_DATA_SET_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CREATE_CLIENT_DATA_FLAG; + static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001; // permit only ClientData creator to write into ClientData + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_REQUEST_FLAG; + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested ClientData when value(s) change + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested ClientData in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_SET_FLAG; + static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_VIEW_SYSTEM_EVENT_DATA; // dwData contains these flags for the "View" System Event + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001; // 2D Panels in cockpit view + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002; // Virtual (3D) panels in cockpit view + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004; // Orthogonal (Map) view + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_SOUND_SYSTEM_EVENT_DATA; // dwData contains these flags for the "Sound" System Event + static const DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001; // Sound Master + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_COMM_BUS_BROADCAST_TO; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_JS = 1 << 0; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_WASM = 1 << 1; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT = 1 << 3; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT_SELF_CALL = 1 << 4; // need SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT, allow the client to broadcast to itself + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_DEFAULT = SIMCONNECT_COMM_BUS_BROADCAST_TO_JS | SIMCONNECT_COMM_BUS_BROADCAST_TO_WASM | SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_ALL_SIMCONNECT = SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT | SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT_SELF_CALL; + static const DWORD SIMCONNECT_COMM_BUS_BROADCAST_TO_ALL = SIMCONNECT_COMM_BUS_BROADCAST_TO_JS | SIMCONNECT_COMM_BUS_BROADCAST_TO_WASM | SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT | SIMCONNECT_COMM_BUS_BROADCAST_TO_SIMCONNECT_SELF_CALL; + + + +//---------------------------------------------------------------------------- +// User-defined enums +//---------------------------------------------------------------------------- + +SIMCONNECT_USER_ENUM SIMCONNECT_NOTIFICATION_GROUP_ID; //client-defined notification group ID +SIMCONNECT_USER_ENUM SIMCONNECT_INPUT_GROUP_ID; //client-defined input group ID +SIMCONNECT_USER_ENUM SIMCONNECT_DATA_DEFINITION_ID; //client-defined data definition ID +SIMCONNECT_USER_ENUM SIMCONNECT_DATA_REQUEST_ID; //client-defined request data ID + +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_EVENT_ID; //client-defined client event ID +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_ID; //client-defined client data ID +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_DEFINITION_ID; //client-defined client data definition ID + + +//---------------------------------------------------------------------------- +// Struct definitions +//---------------------------------------------------------------------------- + +#pragma pack(push, 1) + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV +{ + DWORD dwSize; // record size + DWORD dwVersion; // interface version + DWORD dwID; // see SIMCONNECT_RECV_ID +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION +{ + DWORD dwException; // see SIMCONNECT_EXCEPTION + static const DWORD UNKNOWN_SENDID = 0; + DWORD dwSendID; // see SimConnect_GetLastSentPacketID + static const DWORD UNKNOWN_INDEX = DWORD_MAX; + DWORD dwIndex; // index of parameter that was source of error +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_OPEN : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_OPEN +{ + SIMCONNECT_STRING( szApplicationName, 256); + DWORD dwApplicationVersionMajor; + DWORD dwApplicationVersionMinor; + DWORD dwApplicationBuildMajor; + DWORD dwApplicationBuildMinor; + DWORD dwSimConnectVersionMajor; + DWORD dwSimConnectVersionMinor; + DWORD dwSimConnectBuildMajor; + DWORD dwSimConnectBuildMinor; + DWORD dwReserved1; + DWORD dwReserved2; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_QUIT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_QUIT +{}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT +{ + static const DWORD UNKNOWN_GROUP = DWORD_MAX; + DWORD uGroupID; + DWORD uEventID; + DWORD dwData; // uEventID-dependent context +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FILENAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME +{ + SIMCONNECT_STRING( szFileName, MAX_PATH); // uEventID-dependent context + DWORD dwFlags; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME +{ + SIMCONNECT_SIMOBJECT_TYPE eObjType; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FRAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FRAME +{ + float fFrameRate; + float fSimSpeed; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED +{ + // No event specific data, for now +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED +{ + // No event specific data, for now +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED +{ + // No event specific data, for now +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_EX1 : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT_EX1 +{ + static const DWORD UNKNOWN_GROUP = DWORD_MAX; + DWORD uGroupID; + DWORD uEventID; + + // Doesn t support array so, let s list + DWORD dwData0; + DWORD dwData1; + DWORD dwData2; + DWORD dwData3; + DWORD dwData4; +}; + +// SIMCONNECT_DATA_RACE_RESULT +SIMCONNECT_STRUCT SIMCONNECT_DATA_RACE_RESULT +{ + DWORD dwNumberOfRacers; // The total number of racers + SIMCONNECT_GUID MissionGUID; // The name of the mission to execute, NULL if no mission + SIMCONNECT_STRING( szPlayerName, MAX_PATH); // The name of the player + SIMCONNECT_STRING( szSessionType, MAX_PATH); // The type of the multiplayer session: "LAN", "GAMESPY") + SIMCONNECT_STRING( szAircraft, MAX_PATH); // The aircraft type + SIMCONNECT_STRING( szPlayerRole, MAX_PATH); // The player role in the mission + double fTotalTime; // Total time in seconds, 0 means DNF + double fPenaltyTime; // Total penalty time in seconds + DWORD dwIsDisqualified; // non 0 - disqualified, 0 - not disqualified +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_END : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_END +{ + DWORD dwRacerNumber; // The index of the racer the results are for + SIMCONNECT_DATA_RACE_RESULT RacerData; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_LAP : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_LAP +{ + DWORD dwLapIndex; // The index of the lap the results are for + SIMCONNECT_DATA_RACE_RESULT RacerData; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA +{ + DWORD dwRequestID; + DWORD dwObjectID; + DWORD dwDefineID; + DWORD dwFlags; // SIMCONNECT_DATA_REQUEST_FLAG + DWORD dwentrynumber; // if multiple objects returned, this is number out of . + DWORD dwoutof; // note: starts with 1, not 0. + DWORD dwDefineCount; // data count (number of datums, *not* byte count) + SIMCONNECT_DATAV( dwData, dwDefineID, ); // data begins here, dwDefineCount data items +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE +{ +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLIENT_DATA : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_CLIENT_DATA +{ +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WEATHER_OBSERVATION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_WEATHER_OBSERVATION +{ + DWORD dwRequestID; + SIMCONNECT_STRINGV( szMetar); // Variable length string whose maximum size is MAX_METAR_LENGTH +}; + +static const int SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH = 64; +static const int SIMCONNECT_CLOUD_STATE_ARRAY_SIZE = SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH*SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLOUD_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_CLOUD_STATE +{ + DWORD dwRequestID; + DWORD dwArraySize; + SIMCONNECT_FIXEDTYPE_DATAV(BYTE, rgbData, dwArraySize, U1 /*member of UnmanagedType enum*/ , System::Byte /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ASSIGNED_OBJECT_ID : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID +{ + DWORD dwRequestID; + DWORD dwObjectID; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_RESERVED_KEY : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY +{ + SIMCONNECT_STRING( szChoiceReserved, 30); + SIMCONNECT_STRING( szReservedKey, 50); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SYSTEM_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SYSTEM_STATE +{ + DWORD dwRequestID; + DWORD dwInteger; + float fFloat; + SIMCONNECT_STRING( szString, MAX_PATH); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CUSTOM_ACTION : public SIMCONNECT_RECV_EVENT +{ + SIMCONNECT_GUID guidInstanceId; // Instance id of the action that executed + DWORD dwWaitForCompletion; // Wait for completion flag on the action + SIMCONNECT_STRINGV( szPayLoad); // Variable length string payload associated with the mission action. +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_WEATHER_MODE : public SIMCONNECT_RECV_EVENT +{ + // No event specific data - the new weather mode is in the base structure dwData member. +}; + +// SIMCONNECT_RECV_FACILITIES_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITIES_LIST : public SIMCONNECT_RECV +{ + DWORD dwRequestID; + DWORD dwArraySize; + DWORD dwEntryNumber; // when the array of items is too big for one send, which send this is (0..dwOutOf-1) + DWORD dwOutOf; // total number of transmissions the list is chopped into +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_LIST_TEMPLATE : public SIMCONNECT_RECV +{ + DWORD dwRequestID; + DWORD dwArraySize; + DWORD dwEntryNumber; // when the array of items is too big for one send, which send this is (0..dwOutOf-1) + DWORD dwOutOf; // total number of transmissions the list is chopped into +}; + +// SIMCONNECT_DATA_FACILITY_AIRPORT +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_AIRPORT +{ + SIMCONNECT_STRING(Ident, 9); // ICAO of the object + SIMCONNECT_STRING(Region, 3); // ICAO of the object + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // meters +}; + +// SIMCONNECT_RECV_AIRPORT_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_AIRPORT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_AIRPORT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_AIRPORT /*cli type*/); +}; + +// SIMCONNECT_DATA_FACILITY_WAYPOINT +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_WAYPOINT : public SIMCONNECT_DATA_FACILITY_AIRPORT +{ + float fMagVar; // Magvar in degrees +}; + +// SIMCONNECT_RECV_WAYPOINT_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WAYPOINT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_WAYPOINT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_WAYPOINT /*cli type*/); +}; + +// SIMCONNECT_DATA_FACILITY_NDB +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_NDB : public SIMCONNECT_DATA_FACILITY_WAYPOINT +{ + DWORD fFrequency; // frequency in Hz +}; + +// SIMCONNECT_RECV_NDB_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_NDB_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_NDB, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_NDB /*cli type*/); +}; + +// SIMCONNECT_DATA_FACILITY_VOR +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_VOR : public SIMCONNECT_DATA_FACILITY_NDB +{ + DWORD Flags; // SIMCONNECT_VOR_FLAGS + float fLocalizer; // Localizer in degrees + double GlideLat; // Glide Slope Location (deg, deg, meters) + double GlideLon; + double GlideAlt; + float fGlideSlopeAngle; // Glide Slope in degrees +}; + +// SIMCONNECT_RECV_VOR_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_VOR_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_VOR, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_VOR /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITY_DATA : public SIMCONNECT_RECV +{ + DWORD UserRequestId; + DWORD UniqueRequestId; + DWORD ParentUniqueRequestId; + DWORD Type; + DWORD IsListItem; + DWORD ItemIndex; + DWORD ListSize; + SIMCONNECT_DATAV(Data, Type, ); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITY_DATA_END : public SIMCONNECT_RECV +{ + DWORD RequestId; +}; + +SIMCONNECT_STRUCT SIMCONNECT_ICAO +{ + char Type; + SIMCONNECT_STRING(Ident, 8 + 1); + SIMCONNECT_STRING(Region, 2 + 1); + SIMCONNECT_STRING(Airport, 4 + 1); +}; + +// SIMCONNECT_DATA_LATLONALT +SIMCONNECT_STRUCT SIMCONNECT_DATA_LATLONALT +{ + double Latitude; + double Longitude; + double Altitude; +}; + +SIMCONNECT_STRUCT SIMCONNECT_DATA_PBH +{ + float Pitch; + float Bank; + float Heading; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_FACILITY_MINIMAL +{ + SIMCONNECT_ICAO icao; + SIMCONNECT_DATA_LATLONALT lla; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITY_MINIMAL_LIST : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_FACILITY_MINIMAL, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_FACILITY_MINIMAL /*cli type*/); +}; + +// SIMCONNECT_DATATYPE_INITPOSITION +SIMCONNECT_STRUCT SIMCONNECT_DATA_INITPOSITION +{ + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // feet + double Pitch; // degrees + double Bank; // degrees + double Heading; // degrees + DWORD OnGround; // 1=force to be on the ground + DWORD Airspeed; // knots +}; + + +// SIMCONNECT_DATATYPE_MARKERSTATE +SIMCONNECT_STRUCT SIMCONNECT_DATA_MARKERSTATE +{ + SIMCONNECT_STRING( szMarkerName, 64); + DWORD dwMarkerState; +}; + +// SIMCONNECT_DATATYPE_WAYPOINT +SIMCONNECT_STRUCT SIMCONNECT_DATA_WAYPOINT +{ + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // feet + unsigned long Flags; + double ktsSpeed; // knots + double percentThrottle; +}; + +// SIMCONNECT_DATA_XYZ +SIMCONNECT_STRUCT SIMCONNECT_DATA_XYZ +{ + double x; + double y; + double z; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_JETWAY_DATA +{ + SIMCONNECT_STRING(AirportIcao, 8); + int ParkingIndex; + SIMCONNECT_DATA_LATLONALT Lla; + SIMCONNECT_DATA_PBH Pbh; + int Status; + int Door; + SIMCONNECT_DATA_XYZ ExitDoorRelativePos; + SIMCONNECT_DATA_XYZ MainHandlePos; + SIMCONNECT_DATA_XYZ SecondaryHandle; + SIMCONNECT_DATA_XYZ WheelGroundLock; + DWORD JetwayObjectId; + DWORD AttachedObjectId; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_JETWAY_DATA : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_JETWAY_DATA, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_JETWAY_DATA /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ACTION_CALLBACK : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ACTION_CALLBACK +{ + SIMCONNECT_STRING(szActionID, MAX_PATH); + DWORD cbRequestId; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_INPUT_EVENT_DESCRIPTOR +{ + SIMCONNECT_STRING(Name, 64); // Input event name + UINT64 Hash; // Hash + SIMCONNECT_INPUT_EVENT_TYPE eType; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_INPUT_EVENT_DESCRIPTOR, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_INPUT_EVENT_DESCRIPTOR /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_GET_INPUT_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_GET_INPUT_EVENT +{ + DWORD dwRequestID; + SIMCONNECT_INPUT_EVENT_TYPE eType; + SIMCONNECT_DATAV(Value, eType,); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT : public SIMCONNECT_RECV +{ + UINT64 Hash; + SIMCONNECT_INPUT_EVENT_TYPE eType; + SIMCONNECT_DATAV(Value, eType,); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS : public SIMCONNECT_RECV +{ + UINT64 Hash; + SIMCONNECT_STRING(Value, MAX_PATH); +}; + + +SIMCONNECT_ENUM SIMCONNECT_POSITION_REFERENTIAL +{ + SIMCONNECT_POSITION_REFERENTIAL_NONE, + SIMCONNECT_POSITION_REFERENTIAL_SIMOBJECT, + SIMCONNECT_POSITION_REFERENTIAL_WORLD, + SIMCONNECT_POSITION_REFERENTIAL_EYEPOINT, + SIMCONNECT_POSITION_REFERENTIAL_SIMOBJECT_DATUM, +}; + +// SIMCONNECT_DATATYPE_CAMERA +SIMCONNECT_STRUCT SIMCONNECT_DATA_CAMERA +{ + SIMCONNECT_DATA_XYZ Position; + SIMCONNECT_POSITION_REFERENTIAL PositionReferential; + DWORD PositionReferentialObjectId; + + SIMCONNECT_DATA_XYZ TargetedPos; + SIMCONNECT_DATA_PBH Pbh; + SIMCONNECT_POSITION_REFERENTIAL RotationReferential; + DWORD RotationReferentialObjectId; + + double Fov; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CAMERA_DATA : public SIMCONNECT_RECV +{ + SIMCONNECT_DATA_CAMERA CameraData; +}; + +SIMCONNECT_ENUM SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS +{ + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS_NONE, + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS_START, + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS_SUCCESS, + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS_CANCEL, + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS_FAIL +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CAMERA_WORLD_LOCKER : public SIMCONNECT_RECV +{ + SIMCONNECT_CAMERA_WORLD_LOCKER_STATUS Status; +}; + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CAMERA_DATA_MASK; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_NONE = 0; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_POSITION = 1 << 0; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_ROTATION = 1 << 1; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_TARGETED = 1 << 2; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_FOV = 1 << 3; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_ALL_ROTATION = SIMCONNECT_CAMERA_DATA_MASK_POSITION | SIMCONNECT_CAMERA_DATA_MASK_ROTATION | SIMCONNECT_CAMERA_DATA_MASK_FOV; + static const DWORD SIMCONNECT_CAMERA_DATA_MASK_ALL_TARGETED = SIMCONNECT_CAMERA_DATA_MASK_POSITION | SIMCONNECT_CAMERA_DATA_MASK_TARGETED | SIMCONNECT_CAMERA_DATA_MASK_FOV; + +SIMCONNECT_ENUM SIMCONNECT_CAMERA_AVAILABILITY +{ + SIMCONNECT_CAMERA_NOT_ACQUIRED, + SIMCONNECT_CAMERA_ACQUIRED, + SIMCONNECT_CAMERA_ACQUIRED_BY_OTHER, + SIMCONNECT_CAMERA_USER_DISABLED +}; + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CAMERA_FLAG; + static const DWORD SIMCONNECT_CAMERA_FLAG_INTERACTION = 0x01; + static const DWORD SIMCONNECT_CAMERA_FLAG_ABOVE_GROUND = 0x02; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CAMERA_STATUS : public SIMCONNECT_RECV +{ + DWORD acquiredState = SIMCONNECT_CAMERA_NOT_ACQUIRED; + BOOL bGameControlled = false; +}; + + +SIMCONNECT_REFSTRUCT SIMCONNECT_VERSION_BASE_TYPE +{ + unsigned short Major; + unsigned short Minor; + unsigned short Revision; + unsigned short Build; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_CONTROLLER_ITEM +{ + SIMCONNECT_STRING(DeviceName, 256); + unsigned int DeviceId; + unsigned int ProductId; + unsigned int CompositeID; + SIMCONNECT_VERSION_BASE_TYPE HardwareVersion; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CONTROLLERS_LIST : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_CONTROLLER_ITEM, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_CONTROLLER_ITEM /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_ENUMERATE_SIMOBJECT_LIVERY +{ + SIMCONNECT_STRING(AircraftTitle, 256); + SIMCONNECT_STRING(LiveryName, 256); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_ENUMERATE_SIMOBJECT_LIVERY, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_ENUMERATE_SIMOBJECT_LIVERY /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FLOW_EVENT : public SIMCONNECT_RECV +{ + SIMCONNECT_FLOW_EVENT FlowEvent; + SIMCONNECT_STRING(FltPath, 256); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_CAMERA_DEFINITION_ITEM +{ + SIMCONNECT_STRING(Str, 256); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CAMERA_DEFINITION_LIST : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_CAMERA_DEFINITION_ITEM, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_CAMERA_DEFINITION_ITEM /*cli type*/); +}; + + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_COMM_BUS : public SIMCONNECT_RECV_LIST_TEMPLATE +{ + DWORD uEventID; + SIMCONNECT_STRINGV(rgData); +}; + + +#pragma pack(pop) + +//---------------------------------------------------------------------------- +// End of Struct definitions +//---------------------------------------------------------------------------- + +#if !defined(SIMCONNECTAPI) + #ifdef _MSFS_WASM + #ifdef __INTELLISENSE__ + #define MODULE_EXPORT + #define SIMCONNECTAPI extern "C" HRESULT + #else + #define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) ) + #define SIMCONNECTAPI extern "C" __attribute__((import_module(SIMCONNECT_WASM_MODULE))) HRESULT + #endif + #else + #define MODULE_EXPORT + #define SIMCONNECTAPI extern "C" HRESULT + #endif +#endif + +#ifdef _USE_WEBASSEMBLY_WASM_RT +typedef void (CALLBACK *DispatchProc)(void* wasmInstance, SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); +#else +typedef void (CALLBACK* DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); +#endif // _USE_WEBASSEMBLY_WASM_RT + +SIMCONNECTAPI SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName = ""); +SIMCONNECTAPI SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags); +SIMCONNECTAPI SimConnect_SetSystemEventState(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_STATE dwState); +SIMCONNECTAPI SimConnect_AddClientEventToNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable = FALSE); +SIMCONNECTAPI SimConnect_RemoveClientEvent(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID); +SIMCONNECTAPI SimConnect_SetNotificationGroupPriority(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); +SIMCONNECTAPI SimConnect_ClearNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID); +SIMCONNECTAPI SimConnect_RequestNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD dwReserved = 0, DWORD Flags = 0); +SIMCONNECTAPI SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * DatumName, const char * UnitsName, SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); +SIMCONNECTAPI SimConnect_ClearDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); +SIMCONNECTAPI SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); +SIMCONNECTAPI SimConnect_RequestDataOnSimObjectType(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, DWORD dwRadiusMeters, SIMCONNECT_SIMOBJECT_TYPE type); +SIMCONNECTAPI SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_MapInputEventToClientEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); +SIMCONNECTAPI SimConnect_SetInputGroupPriority(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD uPriority); +SIMCONNECTAPI SimConnect_RemoveInputEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition); +SIMCONNECTAPI SimConnect_ClearInputGroup(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID); +SIMCONNECTAPI SimConnect_SetInputGroupState(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD dwState); +SIMCONNECTAPI SimConnect_RequestReservedKey(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * szKeyChoice1 = "", const char * szKeyChoice2 = "", const char * szKeyChoice3 = ""); +SIMCONNECTAPI SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); +SIMCONNECTAPI SimConnect_UnsubscribeFromSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); +SIMCONNECTAPI SimConnect_WeatherRequestInterpolatedObservation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt); +SIMCONNECTAPI SimConnect_WeatherRequestObservationAtStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); +SIMCONNECTAPI SimConnect_WeatherRequestObservationAtNearestStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon); +SIMCONNECTAPI SimConnect_WeatherCreateStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO, const char * szName, float lat, float lon, float alt); +SIMCONNECTAPI SimConnect_WeatherRemoveStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); +SIMCONNECTAPI SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char * szMETAR); +SIMCONNECTAPI SimConnect_WeatherSetModeServer(HANDLE hSimConnect, DWORD dwPort, DWORD dwSeconds); +SIMCONNECTAPI SimConnect_WeatherSetModeTheme(HANDLE hSimConnect, const char * szThemeName); +SIMCONNECTAPI SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_WeatherSetModeCustom(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_WeatherSetDynamicUpdateRate(HANDLE hSimConnect, DWORD dwRate); +SIMCONNECTAPI SimConnect_WeatherRequestCloudState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float minLat, float minLon, float minAlt, float maxLat, float maxLon, float maxAlt, DWORD dwFlags = 0); +SIMCONNECTAPI SimConnect_WeatherCreateThermal(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt, float radius, float height, float coreRate = 3.0f, float coreTurbulence = 0.05f, float sinkRate = 3.0f, float sinkTurbulence = 0.2f, float coreSize = 0.4f, float coreTransitionSize = 0.1f, float sinkLayerSize = 0.4f, float sinkTransitionSize = 0.1f); +SIMCONNECTAPI SimConnect_WeatherRemoveThermal(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID); +SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char * szContainerTitle, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AISetAircraftFlightPlan(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, const char * szFlightPlanPath, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_ExecuteMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); +SIMCONNECTAPI SimConnect_CompleteCustomMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); +SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_RetrieveString(SIMCONNECT_RECV * pData, DWORD cbData, void * pStringV, char ** pszString, DWORD * pcbString); +SIMCONNECTAPI SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD * pdwError); +SIMCONNECTAPI SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); +SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); +SIMCONNECTAPI SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData); +SIMCONNECTAPI SimConnect_RequestResponseTimes(HANDLE hSimConnect, DWORD nCount, float * fElapsedSeconds); +SIMCONNECTAPI SimConnect_InsertString(char * pDest, DWORD cbDest, void ** ppEnd, DWORD * pcbStringV, const char * pSource); +SIMCONNECTAPI SimConnect_CameraSetRelative6DOF(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg); +SIMCONNECTAPI SimConnect_MenuAddItem(HANDLE hSimConnect, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, DWORD dwData); +SIMCONNECTAPI SimConnect_MenuDeleteItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID); +SIMCONNECTAPI SimConnect_MenuAddSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID, DWORD dwData); +SIMCONNECTAPI SimConnect_MenuDeleteSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID); +SIMCONNECTAPI SimConnect_RequestSystemState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szState); +SIMCONNECTAPI SimConnect_SetSystemState(HANDLE hSimConnect, const char * szState, DWORD dwInteger, float fFloat, const char * szString); +SIMCONNECTAPI SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char * szClientDataName, SIMCONNECT_CLIENT_DATA_ID ClientDataID); +SIMCONNECTAPI SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags); +SIMCONNECTAPI SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwOffset, DWORD dwSizeOrType, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); +SIMCONNECTAPI SimConnect_ClearClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID); +SIMCONNECTAPI SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_PERIOD Period = SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); +SIMCONNECTAPI SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_SET_FLAG Flags, DWORD dwReserved, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_FlightLoad(HANDLE hSimConnect, const char * szFileName); +SIMCONNECTAPI SimConnect_FlightSave(HANDLE hSimConnect, const char * szFileName, const char * szTitle, const char * szDescription, DWORD Flags); +SIMCONNECTAPI SimConnect_FlightPlanLoad(HANDLE hSimConnect, const char * szFileName); +SIMCONNECTAPI SimConnect_Text(HANDLE hSimConnect, SIMCONNECT_TEXT_TYPE type, float fTimeSeconds, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_SubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_UnsubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type); +SIMCONNECTAPI SimConnect_RequestFacilitiesList(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_TransmitClientEvent_EX1(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags, DWORD dwData0, DWORD dwData1 = 0, DWORD dwData2 = 0, DWORD dwData3 = 0, DWORD dwData4 = 0); +SIMCONNECTAPI SimConnect_AddToFacilityDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * FieldName); +SIMCONNECTAPI SimConnect_RequestFacilityData(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * ICAO, const char * Region = ""); +SIMCONNECTAPI SimConnect_SubscribeToFacilities_EX1(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID newElemInRangeRequestID, SIMCONNECT_DATA_REQUEST_ID oldElemOutRangeRequestID); +SIMCONNECTAPI SimConnect_UnsubscribeToFacilities_EX1(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, bool bUnsubscribeNewInRange, bool bUnsubscribeOldOutRange); +SIMCONNECTAPI SimConnect_RequestFacilitiesList_EX1(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_RequestFacilityData_EX1(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * ICAO, const char * Region = "", char Type = 0); +SIMCONNECTAPI SimConnect_RequestJetwayData(HANDLE hSimConnect, const char * AirportIcao, DWORD ArrayCount, int * Indexes); +SIMCONNECTAPI SimConnect_EnumerateControllers(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_MapInputEventToClientEvent_EX1(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); +SIMCONNECTAPI SimConnect_ExecuteAction(HANDLE hSimConnect, DWORD cbRequestID, const char * szActionID, DWORD cbUnitSize, void * pParamValues); +SIMCONNECTAPI SimConnect_EnumerateInputEvents(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_GetInputEvent(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, UINT64 Hash); +SIMCONNECTAPI SimConnect_SetInputEvent(HANDLE hSimConnect, UINT64 Hash, DWORD cbUnitSize, void * Value); +SIMCONNECTAPI SimConnect_SubscribeInputEvent(HANDLE hSimConnect, UINT64 Hash); +SIMCONNECTAPI SimConnect_UnsubscribeInputEvent(HANDLE hSimConnect, UINT64 Hash); +SIMCONNECTAPI SimConnect_EnumerateInputEventParams(HANDLE hSimConnect, UINT64 Hash); +SIMCONNECTAPI SimConnect_AddFacilityDataDefinitionFilter(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * szFilterPath, DWORD cbUnitSize, void * pFilterData); +SIMCONNECTAPI SimConnect_ClearAllFacilityDataDefinitionFilters(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); +SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft_EX1(HANDLE hSimConnect, const char * szContainerTitle, const char * szLivery, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft_EX1(HANDLE hSimConnect, const char * szContainerTitle, const char * szLivery, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateNonATCAircraft_EX1(HANDLE hSimConnect, const char * szContainerTitle, const char * szLivery, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateSimulatedObject_EX1(HANDLE hSimConnect, const char * szContainerTitle, const char * szLivery, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_EnumerateSimObjectsAndLiveries(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_SIMOBJECT_TYPE Type); +SIMCONNECTAPI SimConnect_SubscribeToFlowEvent(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_UnsubscribeToFlowEvent(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_RequestAllFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_CameraAcquire(HANDLE hSimConnect, const char * ClientId); +SIMCONNECTAPI SimConnect_CameraRelease(HANDLE hSimConnect, const char * CameraDefName); +SIMCONNECTAPI SimConnect_CameraGetStatus(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_CameraSet(HANDLE hSimConnect, SIMCONNECT_DATA_CAMERA CameraData, DWORD DataMask); +SIMCONNECTAPI SimConnect_CameraGet(HANDLE hSimConnect, DWORD Referential); +SIMCONNECTAPI SimConnect_CameraEnableFlag(HANDLE hSimConnect, DWORD Flag); +SIMCONNECTAPI SimConnect_CameraDisableFlag(HANDLE hSimConnect, DWORD Flag); +SIMCONNECTAPI SimConnect_SubscribeToCameraStatusUpdate(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_UnsubscribeToCameraStatusUpdate(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_EnumerateCameraDefinitions(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_CameraSetUsingCameraDefinition(HANDLE hSimConnect, const char * cameraDefinition); +SIMCONNECTAPI SimConnect_SubscribeToCommBusEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName); +SIMCONNECTAPI SimConnect_UnsubscribeToCommBusEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); +SIMCONNECTAPI SimConnect_CallCommBusEvent(HANDLE hSimConnect, const char * EventName, SIMCONNECT_COMM_BUS_BROADCAST_TO BroadcastTo, DWORD BufferSize, const char * Data); +SIMCONNECTAPI SimConnect_SubscribeToCameraWorldLockerStatusUpdate(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_UnsubscribeToCameraWorldLockerStatusUpdate(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_RequestCameraWorldLocker(HANDLE hSimConnect, SIMCONNECT_DATA_XYZ lockerPosition, SIMCONNECT_POSITION_REFERENTIAL referential, DWORD objectId); +SIMCONNECTAPI SimConnect_DeleteCameraWorldLocker(HANDLE hSimConnect); + + +#endif // _SIMCONNECT_H_ diff --git a/simulators/FS2024/libsrc/lib/SimConnect.lib b/simulators/FS2024/libsrc/lib/SimConnect.lib new file mode 100644 index 0000000000000000000000000000000000000000..ee403f55b01c374c16092b558d412bff6d085140 GIT binary patch literal 35288 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 { + Null, + Exception(&'a SIMCONNECT_RECV_EXCEPTION), + Open(&'a SIMCONNECT_RECV_OPEN), + Quit(&'a SIMCONNECT_RECV_QUIT), + Event(&'a SIMCONNECT_RECV_EVENT), + EventObjectAddRemove(&'a SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE), + EventFilename(&'a SIMCONNECT_RECV_EVENT_FILENAME), + EventFrame(&'a SIMCONNECT_RECV_EVENT_FRAME), + SimObjectData(&'a SIMCONNECT_RECV_SIMOBJECT_DATA), + SimObjectDataByType(&'a SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE), + WeatherObservation(&'a SIMCONNECT_RECV_WEATHER_OBSERVATION), + CloudState(&'a SIMCONNECT_RECV_CLOUD_STATE), + AssignedObjectId(&'a SIMCONNECT_RECV_ASSIGNED_OBJECT_ID), + ReservedKey(&'a SIMCONNECT_RECV_RESERVED_KEY), + CustomAction(&'a SIMCONNECT_RECV_CUSTOM_ACTION), + SystemState(&'a SIMCONNECT_RECV_SYSTEM_STATE), + ClientData(&'a SIMCONNECT_RECV_CLIENT_DATA), + EventWeatherMode(&'a SIMCONNECT_RECV_EVENT_WEATHER_MODE), + AirportList(&'a SIMCONNECT_RECV_AIRPORT_LIST), + VorList(&'a SIMCONNECT_RECV_VOR_LIST), + NdbList(&'a SIMCONNECT_RECV_NDB_LIST), + WaypointList(&'a SIMCONNECT_RECV_WAYPOINT_LIST), + EventMultiplayerServerStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED), + EventMultiplayerClientStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED), + EventMultiplayerSessionEnded(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED), + EventRaceEnd(&'a SIMCONNECT_RECV_EVENT_RACE_END), + EventRaceLap(&'a SIMCONNECT_RECV_EVENT_RACE_LAP), + EventEx1(&'a SIMCONNECT_RECV_EVENT_EX1), + FacilityData(&'a SIMCONNECT_RECV_FACILITY_DATA), + FacilityDataEnd(&'a SIMCONNECT_RECV_FACILITY_DATA_END), + FacilityMinimalList(&'a SIMCONNECT_RECV_FACILITY_MINIMAL_LIST), + JetwayData(&'a SIMCONNECT_RECV_JETWAY_DATA), + ActionCallback(&'a SIMCONNECT_RECV_ACTION_CALLBACK), + EnumerateInputEvents(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS), + GetInputEvent(&'a SIMCONNECT_RECV_GET_INPUT_EVENT), + SubscribeInputEvent(&'a SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT), + EnumerateInputEventParams(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS), + ControllersList(&'a SIMCONNECT_RECV_CONTROLLERS_LIST), + EnumerateSimObjectAndLiveryList(&'a SIMCONNECT_RECV_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST), + FlowEvent(&'a SIMCONNECT_RECV_FLOW_EVENT), + CameraData(&'a SIMCONNECT_RECV_CAMERA_DATA), + CameraStatus(&'a SIMCONNECT_RECV_CAMERA_STATUS), + CameraDefinitionList(&'a SIMCONNECT_RECV_CAMERA_DEFINITION_LIST), + CommBus(&'a SIMCONNECT_RECV_COMM_BUS), + CameraWorldLocker(&'a SIMCONNECT_RECV_CAMERA_WORLD_LOCKER), +} + +#[derive(Debug)] +pub struct SimConnector { + handle: HANDLE, +} + +impl Default for SimConnector { + fn default() -> Self { + Self { handle: ptr::null_mut() } + } +} + +impl SimConnector { + pub fn new() -> Self { + Self::default() + } + + // ==================== Connection & Lifecycle ==================== + + pub fn connect(&mut self, program_name: &str) -> bool { + let name = cstring(program_name); + + unsafe { + SimConnect_Open( + &mut self.handle, + name.as_ptr(), + ptr::null_mut(), + 0, + ptr::null_mut(), + 0, + ) == 0 + } + } + + pub fn close(&mut self) -> bool { + if self.handle.is_null() { + return true; + } + let result = unsafe { SimConnect_Close(self.handle) == 0 }; + self.handle = ptr::null_mut(); + result + } + + // ==================== Data Definition ==================== + + pub fn add_data_definition( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + datum_name: &str, + units_name: &str, + datum_type: SIMCONNECT_DATATYPE, + epsilon: f32, + datum_id: DWORD, + ) -> bool { + let name = cstring(datum_name); + let units = cstring(units_name); + + unsafe { + SimConnect_AddToDataDefinition( + self.handle, + define_id, + name.as_ptr(), + units.as_ptr(), + datum_type, + epsilon, + datum_id, + ) == 0 + } + } + + pub fn clear_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { + unsafe { SimConnect_ClearDataDefinition(self.handle, define_id) == 0 } + } + + // ==================== Events ==================== + + pub fn map_client_event_to_sim_event( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, + ) -> bool { + let name = cstring(event_name); + unsafe { SimConnect_MapClientEventToSimEvent(self.handle, event_id, name.as_ptr()) == 0 } + } + + pub fn subscribe_to_system_event( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + event_name: &str, + ) -> bool { + let name = cstring(event_name); + unsafe { + SimConnect_SubscribeToSystemEvent(self.handle, event_id, name.as_ptr()) == 0 + } + } + + pub fn unsubscribe_from_system_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_UnsubscribeFromSystemEvent(self.handle, event_id) == 0 } + } + + pub fn set_system_event_state( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + state: SIMCONNECT_STATE, + ) -> bool { + unsafe { SimConnect_SetSystemEventState(self.handle, event_id, state) == 0 } + } + + pub fn transmit_client_event( + &self, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + dw_data: DWORD, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, + ) -> bool { + unsafe { + SimConnect_TransmitClientEvent( + self.handle, + object_id, + event_id, + dw_data, + group_id, + flags, + ) == 0 + } + } + + pub fn add_client_event_to_notification_group( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + maskable: bool, + ) -> bool { + unsafe { + SimConnect_AddClientEventToNotificationGroup( + self.handle, + group_id, + event_id, + maskable as i32, + ) == 0 + } + } + + pub fn set_notification_group_priority( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + priority: DWORD, + ) -> bool { + unsafe { + SimConnect_SetNotificationGroupPriority(self.handle, group_id, priority) == 0 + } + } + + pub fn remove_client_event( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + ) -> bool { + unsafe { SimConnect_RemoveClientEvent(self.handle, group_id, event_id) == 0 } + } + + pub fn clear_notification_group(&self, group_id: SIMCONNECT_NOTIFICATION_GROUP_ID) -> bool { + unsafe { SimConnect_ClearNotificationGroup(self.handle, group_id) == 0 } + } + + pub fn request_notification_group( + &self, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + reserved: DWORD, + flags: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestNotificationGroup(self.handle, group_id, reserved, flags) == 0 + } + } + + pub fn transmit_client_event_ex1( + &self, + object_id: SIMCONNECT_OBJECT_ID, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, + flags: SIMCONNECT_EVENT_FLAG, + data0: DWORD, + data1: DWORD, + data2: DWORD, + data3: DWORD, + data4: DWORD, + ) -> bool { + unsafe { + SimConnect_TransmitClientEvent_EX1( + self.handle, + object_id, + event_id, + group_id, + flags, + data0, + data1, + data2, + data3, + data4, + ) == 0 + } + } + + pub fn request_reserved_key( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + key_choice1: &str, + key_choice2: &str, + key_choice3: &str, + ) -> bool { + let k1 = cstring(key_choice1); + let k2 = cstring(key_choice2); + let k3 = cstring(key_choice3); + + unsafe { + SimConnect_RequestReservedKey( + self.handle, + event_id, + k1.as_ptr(), + k2.as_ptr(), + k3.as_ptr(), + ) == 0 + } + } + + // ==================== Input Events ==================== + + pub fn map_input_event_to_client_event( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_MapInputEventToClientEvent( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, + ) == 0 + } + } + + pub fn map_input_event_to_client_event_ex1( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + down_event: SIMCONNECT_CLIENT_EVENT_ID, + down_return_value: DWORD, + up_event: SIMCONNECT_CLIENT_EVENT_ID, + up_return_value: DWORD, + maskable: bool, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_MapInputEventToClientEvent_EX1( + self.handle, + group_id, + input.as_ptr(), + down_event, + down_return_value, + up_event, + up_return_value, + maskable as i32, + ) == 0 + } + } + + pub fn set_input_group_state(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, state: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupState(self.handle, group_id, state) == 0 } + } + + pub fn set_input_priority(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, priority: DWORD) -> bool { + unsafe { SimConnect_SetInputGroupPriority(self.handle, group_id, priority) == 0 } + } + + pub fn remove_input_event( + &self, + group_id: SIMCONNECT_INPUT_GROUP_ID, + input_definition: &str, + ) -> bool { + let input = cstring(input_definition); + unsafe { + SimConnect_RemoveInputEvent(self.handle, group_id, input.as_ptr()) == 0 + } + } + + pub fn clear_input_group(&self, group_id: SIMCONNECT_INPUT_GROUP_ID) -> bool { + unsafe { SimConnect_ClearInputGroup(self.handle, group_id) == 0 } + } + + // ==================== Data Requests ==================== + + pub fn request_data_on_sim_object( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + period: SIMCONNECT_PERIOD, + flags: SIMCONNECT_DATA_REQUEST_FLAG, + origin: DWORD, + interval: DWORD, + limit: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestDataOnSimObject( + self.handle, + request_id, + define_id, + object_id, + period, + flags, + origin, + interval, + limit, + ) == 0 + } + } + + pub fn request_data_on_sim_object_type( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + radius_in_meters: DWORD, + object_type: SIMCONNECT_SIMOBJECT_TYPE, + ) -> bool { + unsafe { + SimConnect_RequestDataOnSimObjectType( + self.handle, + request_id, + define_id, + radius_in_meters, + object_type, + ) == 0 + } + } + + pub unsafe fn set_data_on_sim_object( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + object_id: SIMCONNECT_OBJECT_ID, + flags: SIMCONNECT_DATA_SET_FLAG, + array_count: DWORD, + size: DWORD, + pntr: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_SetDataOnSimObject( + self.handle, define_id, object_id, flags, array_count, size, pntr, + ) == 0 + } + } + + // ==================== Client Data ==================== + + pub fn create_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + size: DWORD, + flags: SIMCONNECT_CREATE_CLIENT_DATA_FLAG, + ) -> bool { + unsafe { SimConnect_CreateClientData(self.handle, data_id, size, flags) == 0 } + } + + pub fn map_client_data_name_to_id( + &self, + client_data_name: &str, + data_id: SIMCONNECT_CLIENT_DATA_ID, + ) -> bool { + let name = cstring(client_data_name); + unsafe { + SimConnect_MapClientDataNameToID(self.handle, name.as_ptr(), data_id) == 0 + } + } + + pub fn add_to_client_data_definition( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + offset: DWORD, + size_or_type: DWORD, + epsilon: f32, + datum_id: DWORD, + ) -> bool { + unsafe { + SimConnect_AddToClientDataDefinition( + self.handle, define_id, offset, size_or_type, epsilon, datum_id, + ) == 0 + } + } + + pub fn clear_client_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { + unsafe { SimConnect_ClearClientDataDefinition(self.handle, define_id) == 0 } + } + + pub fn request_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + period: SIMCONNECT_CLIENT_DATA_PERIOD, + flags: SIMCONNECT_CLIENT_DATA_REQUEST_FLAG, + origin: DWORD, + interval: DWORD, + limit: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestClientData( + self.handle, + data_id, + request_id, + define_id, + period, + flags, + origin, + interval, + limit, + ) == 0 + } + } + + pub unsafe fn set_client_data( + &self, + data_id: SIMCONNECT_CLIENT_DATA_ID, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + flags: DWORD, + reserved: DWORD, + unit_size: DWORD, + data_set: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_SetClientData( + self.handle, data_id, define_id, flags, reserved, unit_size, data_set, + ) == 0 + } + } + + // ==================== AI Objects ==================== + + pub fn ai_create_parked_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + airport_id: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let airport = cstring(airport_id); + + unsafe { + SimConnect_AICreateParkedATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + airport.as_ptr(), + request_id, + ) == 0 + } + } + + pub fn ai_create_parked_atc_aircraft_ex1( + &self, + container_title: &str, + livery: &str, + tail_number: &str, + airport_id: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let liv = cstring(livery); + let tail = cstring(tail_number); + let airport = cstring(airport_id); + + unsafe { + SimConnect_AICreateParkedATCAircraft_EX1( + self.handle, + title.as_ptr(), + liv.as_ptr(), + tail.as_ptr(), + airport.as_ptr(), + request_id, + ) == 0 + } + } + + pub fn ai_create_enroute_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + flight_number: i32, + flight_plan_path: &str, + flight_plan_position: f64, + touch_and_go: bool, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + let plan = cstring(flight_plan_path); + + unsafe { + SimConnect_AICreateEnrouteATCAircraft( + self.handle, + title.as_ptr(), + tail.as_ptr(), + flight_number, + plan.as_ptr(), + flight_plan_position, + touch_and_go as i32, + request_id, + ) == 0 + } + } + + pub fn ai_create_enroute_atc_aircraft_ex1( + &self, + container_title: &str, + livery: &str, + tail_number: &str, + flight_number: i32, + flight_plan_path: &str, + flight_plan_position: f64, + touch_and_go: bool, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let liv = cstring(livery); + let tail = cstring(tail_number); + let plan = cstring(flight_plan_path); + + unsafe { + SimConnect_AICreateEnrouteATCAircraft_EX1( + self.handle, + title.as_ptr(), + liv.as_ptr(), + tail.as_ptr(), + flight_number, + plan.as_ptr(), + flight_plan_position, + touch_and_go as i32, + request_id, + ) == 0 + } + } + + pub fn ai_create_non_atc_aircraft( + &self, + container_title: &str, + tail_number: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let tail = cstring(tail_number); + + unsafe { + SimConnect_AICreateNonATCAircraft( + self.handle, title.as_ptr(), tail.as_ptr(), init_pos, request_id, + ) == 0 + } + } + + pub fn ai_create_non_atc_aircraft_ex1( + &self, + container_title: &str, + livery: &str, + tail_number: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let liv = cstring(livery); + let tail = cstring(tail_number); + + unsafe { + SimConnect_AICreateNonATCAircraft_EX1( + self.handle, + title.as_ptr(), + liv.as_ptr(), + tail.as_ptr(), + init_pos, + request_id, + ) == 0 + } + } + + pub fn ai_create_simulated_object( + &self, + container_title: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + unsafe { + SimConnect_AICreateSimulatedObject(self.handle, title.as_ptr(), init_pos, request_id) == 0 + } + } + + pub fn ai_create_simulated_object_ex1( + &self, + container_title: &str, + livery: &str, + init_pos: SIMCONNECT_DATA_INITPOSITION, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let title = cstring(container_title); + let liv = cstring(livery); + + unsafe { + SimConnect_AICreateSimulatedObject_EX1( + self.handle, + title.as_ptr(), + liv.as_ptr(), + init_pos, + request_id, + ) == 0 + } + } + + pub fn ai_release_control( + &self, + object_id: SIMCONNECT_OBJECT_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_AIReleaseControl(self.handle, object_id, request_id) == 0 } + } + + pub fn ai_remove_object( + &self, + object_id: SIMCONNECT_OBJECT_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_AIRemoveObject(self.handle, object_id, request_id) == 0 } + } + + pub fn ai_set_aircraft_flight_plan( + &self, + object_id: SIMCONNECT_OBJECT_ID, + flight_plan_path: &str, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + let plan = cstring(flight_plan_path); + unsafe { + SimConnect_AISetAircraftFlightPlan( + self.handle, object_id, plan.as_ptr(), request_id, + ) == 0 + } + } + + // ==================== Weather ==================== + + pub fn weather_request_interpolated_observation( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, + ) -> bool { + unsafe { + SimConnect_WeatherRequestInterpolatedObservation(self.handle, request_id, lat, lon, alt) == 0 + } + } + + pub fn weather_request_observation_at_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + station: &str, + ) -> bool { + let station = cstring(station); + unsafe { + SimConnect_WeatherRequestObservationAtStation(self.handle, request_id, station.as_ptr()) == 0 + } + } + + pub fn weather_request_observation_at_nearest_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + ) -> bool { + unsafe { + SimConnect_WeatherRequestObservationAtNearestStation(self.handle, request_id, lat, lon) == 0 + } + } + + pub fn weather_create_station( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + name: &str, + lat: f32, + lon: f32, + alt: f32, + ) -> bool { + let icao_c = cstring(icao); + let name_c = cstring(name); + + unsafe { + SimConnect_WeatherCreateStation( + self.handle, + request_id, + icao_c.as_ptr(), + name_c.as_ptr(), + lat, + lon, + alt, + ) == 0 + } + } + + pub fn weather_remove_station(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, station: &str) -> bool { + let station = cstring(station); + unsafe { + SimConnect_WeatherRemoveStation(self.handle, request_id, station.as_ptr()) == 0 + } + } + + pub fn weather_set_observation(&self, seconds: DWORD, observation: &str) -> bool { + let obs = cstring(observation); + unsafe { + SimConnect_WeatherSetObservation(self.handle, seconds, obs.as_ptr()) == 0 + } + } + + pub fn weather_set_mode_server(&self, port: DWORD, seconds: DWORD) -> bool { + unsafe { SimConnect_WeatherSetModeServer(self.handle, port, seconds) == 0 } + } + + pub fn weather_set_mode_theme(&self, theme_name: &str) -> bool { + let theme = cstring(theme_name); + unsafe { SimConnect_WeatherSetModeTheme(self.handle, theme.as_ptr()) == 0 } + } + + pub fn weather_set_mode_global(&self) -> bool { + unsafe { SimConnect_WeatherSetModeGlobal(self.handle) == 0 } + } + + pub fn weather_set_mode_custom(&self) -> bool { + unsafe { SimConnect_WeatherSetModeCustom(self.handle) == 0 } + } + + pub fn weather_set_dynamic_update_rate(&self, rate: DWORD) -> bool { + unsafe { SimConnect_WeatherSetDynamicUpdateRate(self.handle, rate) == 0 } + } + + pub fn weather_request_cloud_state( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + min_x: f32, + min_y: f32, + min_z: f32, + max_x: f32, + max_y: f32, + max_z: f32, + flags: DWORD, + ) -> bool { + unsafe { + SimConnect_WeatherRequestCloudState( + self.handle, request_id, min_x, min_y, min_z, max_x, max_y, max_z, flags, + ) == 0 + } + } + + pub fn weather_create_thermal( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + lat: f32, + lon: f32, + alt: f32, + radius: f32, + height: f32, + core_rate: f32, + core_turbulence: f32, + sink_rate: f32, + sink_turbulence: f32, + core_size: f32, + core_transition_size: f32, + sink_layer_size: f32, + sink_transition_size: f32, + ) -> bool { + unsafe { + SimConnect_WeatherCreateThermal( + self.handle, + request_id, + lat, + lon, + alt, + radius, + height, + core_rate, + core_turbulence, + sink_rate, + sink_turbulence, + core_size, + core_transition_size, + sink_layer_size, + sink_transition_size, + ) == 0 + } + } + + pub fn weather_remove_thermal(&self, object_id: SIMCONNECT_OBJECT_ID) -> bool { + unsafe { SimConnect_WeatherRemoveThermal(self.handle, object_id) == 0 } + } + + // ==================== Mission & System ==================== + + pub fn execute_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_ExecuteMissionAction(self.handle, instance_id) == 0 } + } + + pub fn complete_custom_mission_action(&self, instance_id: GUID) -> bool { + unsafe { SimConnect_CompleteCustomMissionAction(self.handle, instance_id) == 0 } + } + + pub fn request_system_state(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, state: &str) -> bool { + let state = cstring(state); + unsafe { SimConnect_RequestSystemState(self.handle, request_id, state.as_ptr()) == 0 } + } + + pub fn set_system_state(&self, state: &str, integer: DWORD, float_val: f32, string_val: &str) -> bool { + let state_c = cstring(state); + let string_c = cstring(string_val); + + unsafe { + SimConnect_SetSystemState( + self.handle, + state_c.as_ptr(), + integer, + float_val, + string_c.as_ptr(), + ) == 0 + } + } + + pub fn flight_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightLoad(self.handle, name.as_ptr()) == 0 } + } + + pub fn flight_save(&self, file_name: &str, title: &str, description: &str, flags: DWORD) -> bool { + let name = cstring(file_name); + let t = cstring(title); + let d = cstring(description); + unsafe { SimConnect_FlightSave(self.handle, name.as_ptr(), t.as_ptr(), d.as_ptr(), flags) == 0 } + } + + pub fn flight_plan_load(&self, file_name: &str) -> bool { + let name = cstring(file_name); + unsafe { SimConnect_FlightPlanLoad(self.handle, name.as_ptr()) == 0 } + } + + // ==================== Facilities ==================== + + pub fn subscribe_to_facilities( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_SubscribeToFacilities(self.handle, list_type, request_id) == 0 } + } + + pub fn unsubscribe_to_facilities(&self, list_type: SIMCONNECT_FACILITY_LIST_TYPE) -> bool { + unsafe { SimConnect_UnsubscribeToFacilities(self.handle, list_type) == 0 } + } + + pub fn request_facilities_list( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_RequestFacilitiesList(self.handle, list_type, request_id) == 0 } + } + + pub fn request_all_facilities( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { SimConnect_RequestAllFacilities(self.handle, list_type, request_id) == 0 } + } + + pub fn add_to_facility_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID, field_name: &str) -> bool { + let field = cstring(field_name); + unsafe { SimConnect_AddToFacilityDefinition(self.handle, define_id, field.as_ptr()) == 0 } + } + + pub fn request_facility_data( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + region: Option<&str>, + ) -> bool { + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); + unsafe { + SimConnect_RequestFacilityData( + self.handle, + define_id, + request_id, + icao.as_ptr(), + region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + ) == 0 + } + } + + pub fn subscribe_to_facilities_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + new_in_range_request_id: SIMCONNECT_DATA_REQUEST_ID, + old_out_of_range_request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { + SimConnect_SubscribeToFacilities_EX1( + self.handle, + list_type, + new_in_range_request_id, + old_out_of_range_request_id, + ) == 0 + } + } + + pub fn unsubscribe_to_facilities_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + unsubscribe_new_in_range: bool, + unsubscribe_old_out_of_range: bool, + ) -> bool { + unsafe { + SimConnect_UnsubscribeToFacilities_EX1( + self.handle, + list_type, + unsubscribe_new_in_range, + unsubscribe_old_out_of_range, + ) == 0 + } + } + + pub fn request_facilities_list_ex1( + &self, + list_type: SIMCONNECT_FACILITY_LIST_TYPE, + request_id: SIMCONNECT_DATA_REQUEST_ID, + ) -> bool { + unsafe { + SimConnect_RequestFacilitiesList_EX1(self.handle, list_type, request_id) == 0 + } + } + + pub fn request_facility_data_ex1( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + request_id: SIMCONNECT_DATA_REQUEST_ID, + icao: &str, + region: Option<&str>, + type_: Option, + ) -> bool { + let icao = cstring(icao); + let region = region.map(|s| cstring(s)); + unsafe { + SimConnect_RequestFacilityData_EX1( + self.handle, + define_id, + request_id, + icao.as_ptr(), + region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + type_.unwrap_or(0) as ::std::os::raw::c_char, + ) == 0 + } + } + + pub unsafe fn request_jetway_data( + &self, + airport_icao: &str, + array_count: DWORD, + indexes: *mut i32, + ) -> bool { + let icao = cstring(airport_icao); + unsafe { + SimConnect_RequestJetwayData(self.handle, icao.as_ptr(), array_count, indexes) == 0 + } + } + + pub fn add_facility_data_definition_filter( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + filter_path: &str, + filter_data: *const std::os::raw::c_void, + cb_unit_size: DWORD, + ) -> bool { + let path = cstring(filter_path); + unsafe { + SimConnect_AddFacilityDataDefinitionFilter( + self.handle, + define_id, + path.as_ptr(), + cb_unit_size, + filter_data as *mut _, + ) == 0 + } + } + + pub fn clear_all_facility_data_definition_filters( + &self, + define_id: SIMCONNECT_DATA_DEFINITION_ID, + ) -> bool { + unsafe { + SimConnect_ClearAllFacilityDataDefinitionFilters(self.handle, define_id) == 0 + } + } + + // ==================== Camera ==================== + + pub fn camera_set_relative_6dof( + &self, + delta_x: f32, + delta_y: f32, + delta_z: f32, + pitch: f32, + bank: f32, + heading: f32, + ) -> bool { + unsafe { + SimConnect_CameraSetRelative6DOF( + self.handle, delta_x, delta_y, delta_z, pitch, bank, heading, + ) == 0 + } + } + + pub fn camera_acquire(&self, client_id: &str) -> bool { + let id = cstring(client_id); + unsafe { SimConnect_CameraAcquire(self.handle, id.as_ptr()) == 0 } + } + + pub fn camera_release(&self, camera_def_name: &str) -> bool { + let name = cstring(camera_def_name); + unsafe { SimConnect_CameraRelease(self.handle, name.as_ptr()) == 0 } + } + + pub fn camera_get_status(&self) -> bool { + unsafe { SimConnect_CameraGetStatus(self.handle) == 0 } + } + + pub unsafe fn camera_set(&self, camera_data: SIMCONNECT_DATA_CAMERA, data_mask: DWORD) -> bool { + unsafe { SimConnect_CameraSet(self.handle, camera_data, data_mask) == 0 } + } + + pub fn camera_get(&self, referential: DWORD) -> bool { + unsafe { SimConnect_CameraGet(self.handle, referential) == 0 } + } + + pub fn camera_enable_flag(&self, flag: DWORD) -> bool { + unsafe { SimConnect_CameraEnableFlag(self.handle, flag) == 0 } + } + + pub fn camera_disable_flag(&self, flag: DWORD) -> bool { + unsafe { SimConnect_CameraDisableFlag(self.handle, flag) == 0 } + } + + pub fn subscribe_to_camera_status_update(&self) -> bool { + unsafe { SimConnect_SubscribeToCameraStatusUpdate(self.handle) == 0 } + } + + pub fn unsubscribe_to_camera_status_update(&self) -> bool { + unsafe { SimConnect_UnsubscribeToCameraStatusUpdate(self.handle) == 0 } + } + + pub fn enumerate_camera_definitions(&self) -> bool { + unsafe { SimConnect_EnumerateCameraDefinitions(self.handle) == 0 } + } + + pub fn camera_set_using_camera_definition(&self, camera_definition: &str) -> bool { + let def = cstring(camera_definition); + unsafe { SimConnect_CameraSetUsingCameraDefinition(self.handle, def.as_ptr()) == 0 } + } + + pub fn subscribe_to_camera_world_locker_status_update(&self) -> bool { + unsafe { SimConnect_SubscribeToCameraWorldLockerStatusUpdate(self.handle) == 0 } + } + + pub fn unsubscribe_to_camera_world_locker_status_update(&self) -> bool { + unsafe { SimConnect_UnsubscribeToCameraWorldLockerStatusUpdate(self.handle) == 0 } + } + + pub unsafe fn request_camera_world_locker( + &self, + locker_position: SIMCONNECT_DATA_XYZ, + referential: SIMCONNECT_POSITION_REFERENTIAL, + object_id: DWORD, + ) -> bool { + unsafe { + SimConnect_RequestCameraWorldLocker(self.handle, locker_position, referential, object_id) == 0 + } + } + + pub fn delete_camera_world_locker(&self) -> bool { + unsafe { SimConnect_DeleteCameraWorldLocker(self.handle) == 0 } + } + + // ==================== CommBus ==================== + + pub fn subscribe_to_comm_bus_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID, event_name: &str) -> bool { + let name = cstring(event_name); + unsafe { SimConnect_SubscribeToCommBusEvent(self.handle, event_id, name.as_ptr()) == 0 } + } + + pub fn unsubscribe_to_comm_bus_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_UnsubscribeToCommBusEvent(self.handle, event_id) == 0 } + } + + pub unsafe fn call_comm_bus_event( + &self, + event_name: &str, + broadcast_to: SIMCONNECT_COMM_BUS_BROADCAST_TO, + buffer_size: DWORD, + data: *const std::os::raw::c_char, + ) -> bool { + let name = cstring(event_name); + unsafe { + SimConnect_CallCommBusEvent( + self.handle, + name.as_ptr(), + broadcast_to, + buffer_size, + data, + ) == 0 + } + } + + // ==================== Flow Events ==================== + + pub fn subscribe_to_flow_event(&self) -> bool { + unsafe { SimConnect_SubscribeToFlowEvent(self.handle) == 0 } + } + + pub fn unsubscribe_to_flow_event(&self) -> bool { + unsafe { SimConnect_UnsubscribeToFlowEvent(self.handle) == 0 } + } + + // ==================== Menu ==================== + + pub fn menu_add_item( + &self, + menu_item: &str, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, + ) -> bool { + let item = cstring(menu_item); + unsafe { SimConnect_MenuAddItem(self.handle, item.as_ptr(), event_id, data) == 0 } + } + + pub fn menu_add_sub_item( + &self, + menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + menu_item: &str, + sub_menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, + data: DWORD, + ) -> bool { + let item = cstring(menu_item); + unsafe { + SimConnect_MenuAddSubItem(self.handle, menu_event_id, item.as_ptr(), sub_menu_event_id, data) == 0 + } + } + + pub fn menu_delete_item(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { + unsafe { SimConnect_MenuDeleteItem(self.handle, event_id) == 0 } + } + + pub fn menu_delete_sub_item( + &self, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + sub_event_id: SIMCONNECT_CLIENT_EVENT_ID, + ) -> bool { + unsafe { SimConnect_MenuDeleteSubItem(self.handle, event_id, sub_event_id) == 0 } + } + + // ==================== Other ==================== + + pub fn enumerate_controllers(&self) -> bool { + unsafe { SimConnect_EnumerateControllers(self.handle) == 0 } + } + + pub fn enumerate_sim_objects_and_liveries( + &self, + request_id: SIMCONNECT_DATA_REQUEST_ID, + object_type: SIMCONNECT_SIMOBJECT_TYPE, + ) -> bool { + unsafe { + SimConnect_EnumerateSimObjectsAndLiveries(self.handle, request_id, object_type) == 0 + } + } + + pub fn enumerate_input_events(&self, request_id: SIMCONNECT_DATA_REQUEST_ID) -> bool { + unsafe { SimConnect_EnumerateInputEvents(self.handle, request_id) == 0 } + } + + pub fn get_input_event(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, hash: u64) -> bool { + unsafe { SimConnect_GetInputEvent(self.handle, request_id, hash) == 0 } + } + + pub unsafe fn set_input_event( + &self, + hash: u64, + unit_size: DWORD, + value: *mut std::os::raw::c_void, + ) -> bool { + unsafe { SimConnect_SetInputEvent(self.handle, hash, unit_size, value) == 0 } + } + + pub fn subscribe_input_event(&self, hash: u64) -> bool { + unsafe { SimConnect_SubscribeInputEvent(self.handle, hash) == 0 } + } + + pub fn unsubscribe_input_event(&self, hash: u64) -> bool { + unsafe { SimConnect_UnsubscribeInputEvent(self.handle, hash) == 0 } + } + + pub fn enumerate_input_event_params(&self, hash: u64) -> bool { + unsafe { SimConnect_EnumerateInputEventParams(self.handle, hash) == 0 } + } + + pub unsafe fn execute_action( + &self, + request_id: DWORD, + action_id: &str, + unit_size: DWORD, + param_values: *mut std::os::raw::c_void, + ) -> bool { + let action = cstring(action_id); + unsafe { + SimConnect_ExecuteAction(self.handle, request_id, action.as_ptr(), unit_size, param_values) == 0 + } + } + + pub unsafe fn text( + &self, + text_type: SIMCONNECT_TEXT_TYPE, + time_in_seconds: f32, + event_id: SIMCONNECT_CLIENT_EVENT_ID, + unit_size: DWORD, + data_set: *mut std::os::raw::c_void, + ) -> bool { + unsafe { + SimConnect_Text(self.handle, text_type, time_in_seconds, event_id, unit_size, data_set) == 0 + } + } + + pub unsafe fn get_last_sent_packet_id(&self, error: *mut DWORD) -> bool { + unsafe { SimConnect_GetLastSentPacketID(self.handle, error) == 0 } + } + + pub unsafe fn call_dispatch( + &self, + dispatch_callback: DispatchProc, + context: *mut std::os::raw::c_void, + ) -> bool { + unsafe { SimConnect_CallDispatch(self.handle, dispatch_callback, context) == 0 } + } + + pub unsafe fn request_response_times(&self, count: DWORD, elapsed_seconds: *mut f32) -> bool { + unsafe { SimConnect_RequestResponseTimes(self.handle, count, elapsed_seconds) == 0 } + } + + // ==================== String Utilities ==================== + + pub unsafe fn retrieve_string( + p_data: *mut SIMCONNECT_RECV, + cb_data: DWORD, + p_string_v: *mut std::os::raw::c_void, + psz_string: *mut *mut std::os::raw::c_char, + pcb_string: *mut DWORD, + ) -> bool { + unsafe { + SimConnect_RetrieveString(p_data, cb_data, p_string_v, psz_string, pcb_string) == 0 + } + } + + pub unsafe fn insert_string( + p_dest: *mut std::os::raw::c_char, + cb_dest: DWORD, + pp_end: *mut *mut std::os::raw::c_void, + pcb_string: *mut DWORD, + p_source: *const std::os::raw::c_char, + ) -> bool { + unsafe { + SimConnect_InsertString(p_dest, cb_dest, pp_end, pcb_string, p_source) == 0 + } + } + + // ==================== Main Message Loop ==================== + + pub fn get_next_message(&self) -> Result, &str> { + unsafe { + let mut data_buf: *mut SIMCONNECT_RECV = ptr::null_mut(); + let mut size_buf: DWORD = 0; + + if SimConnect_GetNextDispatch(self.handle, &mut data_buf, &mut size_buf) != 0 { + return Err("Failed getting data from SimConnect"); + } + + if data_buf.is_null() { + return Ok(DispatchResult::Null); + } + + match (*data_buf).dwID as SIMCONNECT_RECV_ID { + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(DispatchResult::Null), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => Ok(DispatchResult::Exception(&*(data_buf as *const SIMCONNECT_RECV_EXCEPTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Ok(DispatchResult::Open(&*(data_buf as *const SIMCONNECT_RECV_OPEN))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Ok(DispatchResult::Quit(&*(data_buf as *const SIMCONNECT_RECV_QUIT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => Ok(DispatchResult::Event(&*(data_buf as *const SIMCONNECT_RECV_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE => Ok(DispatchResult::EventObjectAddRemove(&*(data_buf as *const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FILENAME => Ok(DispatchResult::EventFilename(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FILENAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FRAME => Ok(DispatchResult::EventFrame(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FRAME))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => Ok(DispatchResult::SimObjectData(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE => Ok(DispatchResult::SimObjectDataByType(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WEATHER_OBSERVATION => Ok(DispatchResult::WeatherObservation(&*(data_buf as *const SIMCONNECT_RECV_WEATHER_OBSERVATION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLOUD_STATE => Ok(DispatchResult::CloudState(&*(data_buf as *const SIMCONNECT_RECV_CLOUD_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID => Ok(DispatchResult::AssignedObjectId(&*(data_buf as *const SIMCONNECT_RECV_ASSIGNED_OBJECT_ID))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_RESERVED_KEY => Ok(DispatchResult::ReservedKey(&*(data_buf as *const SIMCONNECT_RECV_RESERVED_KEY))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CUSTOM_ACTION => Ok(DispatchResult::CustomAction(&*(data_buf as *const SIMCONNECT_RECV_CUSTOM_ACTION))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SYSTEM_STATE => Ok(DispatchResult::SystemState(&*(data_buf as *const SIMCONNECT_RECV_SYSTEM_STATE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLIENT_DATA => Ok(DispatchResult::ClientData(&*(data_buf as *const SIMCONNECT_RECV_CLIENT_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE => Ok(DispatchResult::EventWeatherMode(&*(data_buf as *const SIMCONNECT_RECV_EVENT_WEATHER_MODE))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => Ok(DispatchResult::AirportList(&*(data_buf as *const SIMCONNECT_RECV_AIRPORT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_VOR_LIST => Ok(DispatchResult::VorList(&*(data_buf as *const SIMCONNECT_RECV_VOR_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NDB_LIST => Ok(DispatchResult::NdbList(&*(data_buf as *const SIMCONNECT_RECV_NDB_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WAYPOINT_LIST => Ok(DispatchResult::WaypointList(&*(data_buf as *const SIMCONNECT_RECV_WAYPOINT_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED => Ok(DispatchResult::EventMultiplayerServerStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED => Ok(DispatchResult::EventMultiplayerClientStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED => Ok(DispatchResult::EventMultiplayerSessionEnded(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_END => Ok(DispatchResult::EventRaceEnd(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_LAP => Ok(DispatchResult::EventRaceLap(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_LAP))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_EX1 => Ok(DispatchResult::EventEx1(&*(data_buf as *const SIMCONNECT_RECV_EVENT_EX1))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA => Ok(DispatchResult::FacilityData(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA_END => Ok(DispatchResult::FacilityDataEnd(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA_END))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST => Ok(DispatchResult::FacilityMinimalList(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_MINIMAL_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_JETWAY_DATA => Ok(DispatchResult::JetwayData(&*(data_buf as *const SIMCONNECT_RECV_JETWAY_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ACTION_CALLBACK => Ok(DispatchResult::ActionCallback(&*(data_buf as *const SIMCONNECT_RECV_ACTION_CALLBACK))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS => Ok(DispatchResult::EnumerateInputEvents(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_GET_INPUT_EVENT => Ok(DispatchResult::GetInputEvent(&*(data_buf as *const SIMCONNECT_RECV_GET_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT => Ok(DispatchResult::SubscribeInputEvent(&*(data_buf as *const SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS => Ok(DispatchResult::EnumerateInputEventParams(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CONTROLLERS_LIST => Ok(DispatchResult::ControllersList(&*(data_buf as *const SIMCONNECT_RECV_CONTROLLERS_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST => Ok(DispatchResult::EnumerateSimObjectAndLiveryList(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_SIMOBJECT_AND_LIVERY_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FLOW_EVENT => Ok(DispatchResult::FlowEvent(&*(data_buf as *const SIMCONNECT_RECV_FLOW_EVENT))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CAMERA_DATA => Ok(DispatchResult::CameraData(&*(data_buf as *const SIMCONNECT_RECV_CAMERA_DATA))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CAMERA_STATUS => Ok(DispatchResult::CameraStatus(&*(data_buf as *const SIMCONNECT_RECV_CAMERA_STATUS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CAMERA_DEFINITION_LIST => Ok(DispatchResult::CameraDefinitionList(&*(data_buf as *const SIMCONNECT_RECV_CAMERA_DEFINITION_LIST))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_COMM_BUS => Ok(DispatchResult::CommBus(&*(data_buf as *const SIMCONNECT_RECV_COMM_BUS))), + SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CAMERA_WORLD_LOCKER => Ok(DispatchResult::CameraWorldLocker(&*(data_buf as *const SIMCONNECT_RECV_CAMERA_WORLD_LOCKER))), + _ => Err("Unhandled RECV_ID"), + } + } + } +} + +impl Drop for SimConnector { + fn drop(&mut self) { + if !self.handle.is_null() { + let _ = self.close(); + } + } +} + +#[inline] +fn cstring(s: &str) -> CString { + CString::new(s).expect("string contained interior nul byte") +} diff --git a/src/lib.rs b/src/lib.rs index 1cc9599..951d241 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,1193 +1,5 @@ -#![allow(clippy::too_many_arguments, clippy::missing_safety_doc)] -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] +#[cfg(feature = "fs2020")] +pub use simconnect_fs2020 as fs2020; -use std::ffi::CString; -use std::ptr; - -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -#[derive(Debug)] -pub enum DispatchResult<'a> { - Null, - Exception(&'a SIMCONNECT_RECV_EXCEPTION), - Open(&'a SIMCONNECT_RECV_OPEN), - Quit(&'a SIMCONNECT_RECV_QUIT), - Event(&'a SIMCONNECT_RECV_EVENT), - EventObjectAddRemove(&'a SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE), - EventFilename(&'a SIMCONNECT_RECV_EVENT_FILENAME), - EventFrame(&'a SIMCONNECT_RECV_EVENT_FRAME), - SimObjectData(&'a SIMCONNECT_RECV_SIMOBJECT_DATA), - SimObjectDataByType(&'a SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE), - WeatherObservation(&'a SIMCONNECT_RECV_WEATHER_OBSERVATION), - CloudState(&'a SIMCONNECT_RECV_CLOUD_STATE), - AssignedObjectId(&'a SIMCONNECT_RECV_ASSIGNED_OBJECT_ID), - ReservedKey(&'a SIMCONNECT_RECV_RESERVED_KEY), - CustomAction(&'a SIMCONNECT_RECV_CUSTOM_ACTION), - SystemState(&'a SIMCONNECT_RECV_SYSTEM_STATE), - ClientData(&'a SIMCONNECT_RECV_CLIENT_DATA), - EventWeatherMode(&'a SIMCONNECT_RECV_EVENT_WEATHER_MODE), - AirportList(&'a SIMCONNECT_RECV_AIRPORT_LIST), - VorList(&'a SIMCONNECT_RECV_VOR_LIST), - NdbList(&'a SIMCONNECT_RECV_NDB_LIST), - WaypointList(&'a SIMCONNECT_RECV_WAYPOINT_LIST), - EventMultiplayerServerStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED), - EventMultiplayerClientStarted(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED), - EventMultiplayerSessionEnded(&'a SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED), - EventRaceEnd(&'a SIMCONNECT_RECV_EVENT_RACE_END), - EventRaceLap(&'a SIMCONNECT_RECV_EVENT_RACE_LAP), - EventEx1(&'a SIMCONNECT_RECV_EVENT_EX1), - FacilityData(&'a SIMCONNECT_RECV_FACILITY_DATA), - FacilityDataEnd(&'a SIMCONNECT_RECV_FACILITY_DATA_END), - FacilityMinimalList(&'a SIMCONNECT_RECV_FACILITY_MINIMAL_LIST), - JetwayData(&'a SIMCONNECT_RECV_JETWAY_DATA), - ActionCallback(&'a SIMCONNECT_RECV_ACTION_CALLBACK), - EnumerateInputEvents(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS), - GetInputEvent(&'a SIMCONNECT_RECV_GET_INPUT_EVENT), - SubscribeInputEvent(&'a SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT), - EnumerateInputEventParams(&'a SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS), - ControllersList(&'a SIMCONNECT_RECV_CONTROLLERS_LIST), -} - -#[derive(Debug)] -pub struct SimConnector { - handle: HANDLE, -} - -impl Default for SimConnector { - fn default() -> Self { - Self { handle: ptr::null_mut() } - } -} - -impl SimConnector { - pub fn new() -> Self { - Self::default() - } - - // ==================== Connection & Lifecycle ==================== - - pub fn connect(&mut self, program_name: &str) -> bool { - let name = cstring(program_name); - - unsafe { - SimConnect_Open( - &mut self.handle, - name.as_ptr(), - ptr::null_mut(), - 0, - ptr::null_mut(), - 0, - ) == 0 - } - } - - pub fn close(&mut self) -> bool { - if self.handle.is_null() { - return true; - } - let result = unsafe { SimConnect_Close(self.handle) == 0 }; - self.handle = ptr::null_mut(); - result - } - - // ==================== Data Definition ==================== - - pub fn add_data_definition( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - datum_name: &str, - units_name: &str, - datum_type: SIMCONNECT_DATATYPE, - epsilon: f32, - datum_id: DWORD, - ) -> bool { - let name = cstring(datum_name); - let units = cstring(units_name); - - unsafe { - SimConnect_AddToDataDefinition( - self.handle, - define_id, - name.as_ptr(), - units.as_ptr(), - datum_type, - epsilon, - datum_id, - ) == 0 - } - } - - pub fn clear_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { - unsafe { SimConnect_ClearDataDefinition(self.handle, define_id) == 0 } - } - - // ==================== Events ==================== - - pub fn map_client_event_to_sim_event( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - event_name: &str, - ) -> bool { - let name = cstring(event_name); - unsafe { SimConnect_MapClientEventToSimEvent(self.handle, event_id, name.as_ptr()) == 0 } - } - - pub fn subscribe_to_system_event( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - event_name: &str, - ) -> bool { - let name = cstring(event_name); - unsafe { - SimConnect_SubscribeToSystemEvent(self.handle, event_id, name.as_ptr()) == 0 - } - } - - pub fn unsubscribe_from_system_event(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { - unsafe { SimConnect_UnsubscribeFromSystemEvent(self.handle, event_id) == 0 } - } - - pub fn set_system_event_state( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - state: SIMCONNECT_STATE, - ) -> bool { - unsafe { SimConnect_SetSystemEventState(self.handle, event_id, state) == 0 } - } - - pub fn transmit_client_event( - &self, - object_id: SIMCONNECT_OBJECT_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - dw_data: DWORD, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - flags: SIMCONNECT_EVENT_FLAG, - ) -> bool { - unsafe { - SimConnect_TransmitClientEvent( - self.handle, - object_id, - event_id, - dw_data, - group_id, - flags, - ) == 0 - } - } - - pub fn add_client_event_to_notification_group( - &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - maskable: bool, - ) -> bool { - unsafe { - SimConnect_AddClientEventToNotificationGroup( - self.handle, - group_id, - event_id, - maskable as i32, - ) == 0 - } - } - - pub fn set_notification_group_priority( - &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - priority: DWORD, - ) -> bool { - unsafe { - SimConnect_SetNotificationGroupPriority(self.handle, group_id, priority) == 0 - } - } - - pub fn remove_client_event( - &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - ) -> bool { - unsafe { SimConnect_RemoveClientEvent(self.handle, group_id, event_id) == 0 } - } - - pub fn clear_notification_group(&self, group_id: SIMCONNECT_NOTIFICATION_GROUP_ID) -> bool { - unsafe { SimConnect_ClearNotificationGroup(self.handle, group_id) == 0 } - } - - pub fn request_notification_group( - &self, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - reserved: DWORD, - flags: DWORD, - ) -> bool { - unsafe { - SimConnect_RequestNotificationGroup(self.handle, group_id, reserved, flags) == 0 - } - } - - pub fn transmit_client_event_ex1( - &self, - object_id: SIMCONNECT_OBJECT_ID, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - group_id: SIMCONNECT_NOTIFICATION_GROUP_ID, - flags: SIMCONNECT_EVENT_FLAG, - data0: DWORD, - data1: DWORD, - data2: DWORD, - data3: DWORD, - data4: DWORD, - ) -> bool { - unsafe { - SimConnect_TransmitClientEvent_EX1( - self.handle, - object_id, - event_id, - group_id, - flags, - data0, - data1, - data2, - data3, - data4, - ) == 0 - } - } - - pub fn request_reserved_key( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - key_choice1: &str, - key_choice2: &str, - key_choice3: &str, - ) -> bool { - let k1 = cstring(key_choice1); - let k2 = cstring(key_choice2); - let k3 = cstring(key_choice3); - - unsafe { - SimConnect_RequestReservedKey( - self.handle, - event_id, - k1.as_ptr(), - k2.as_ptr(), - k3.as_ptr(), - ) == 0 - } - } - - // ==================== Input Events ==================== - - pub fn map_input_event_to_client_event( - &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, - down_event: SIMCONNECT_CLIENT_EVENT_ID, - down_return_value: DWORD, - up_event: SIMCONNECT_CLIENT_EVENT_ID, - up_return_value: DWORD, - maskable: bool, - ) -> bool { - let input = cstring(input_definition); - unsafe { - SimConnect_MapInputEventToClientEvent( - self.handle, - group_id, - input.as_ptr(), - down_event, - down_return_value, - up_event, - up_return_value, - maskable as i32, - ) == 0 - } - } - - pub fn map_input_event_to_client_event_ex1( - &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, - down_event: SIMCONNECT_CLIENT_EVENT_ID, - down_return_value: DWORD, - up_event: SIMCONNECT_CLIENT_EVENT_ID, - up_return_value: DWORD, - maskable: bool, - ) -> bool { - let input = cstring(input_definition); - unsafe { - SimConnect_MapInputEventToClientEvent_EX1( - self.handle, - group_id, - input.as_ptr(), - down_event, - down_return_value, - up_event, - up_return_value, - maskable as i32, - ) == 0 - } - } - - pub fn set_input_group_state(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, state: DWORD) -> bool { - unsafe { SimConnect_SetInputGroupState(self.handle, group_id, state) == 0 } - } - - pub fn set_input_priority(&self, group_id: SIMCONNECT_INPUT_GROUP_ID, priority: DWORD) -> bool { - unsafe { SimConnect_SetInputGroupPriority(self.handle, group_id, priority) == 0 } - } - - pub fn remove_input_event( - &self, - group_id: SIMCONNECT_INPUT_GROUP_ID, - input_definition: &str, - ) -> bool { - let input = cstring(input_definition); - unsafe { - SimConnect_RemoveInputEvent(self.handle, group_id, input.as_ptr()) == 0 - } - } - - pub fn clear_input_group(&self, group_id: SIMCONNECT_INPUT_GROUP_ID) -> bool { - unsafe { SimConnect_ClearInputGroup(self.handle, group_id) == 0 } - } - - // ==================== Data Requests ==================== - - pub fn request_data_on_sim_object( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - object_id: SIMCONNECT_OBJECT_ID, - period: SIMCONNECT_PERIOD, - flags: SIMCONNECT_DATA_REQUEST_FLAG, - origin: DWORD, - interval: DWORD, - limit: DWORD, - ) -> bool { - unsafe { - SimConnect_RequestDataOnSimObject( - self.handle, - request_id, - define_id, - object_id, - period, - flags, - origin, - interval, - limit, - ) == 0 - } - } - - pub fn request_data_on_sim_object_type( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - radius_in_meters: DWORD, - object_type: SIMCONNECT_SIMOBJECT_TYPE, - ) -> bool { - unsafe { - SimConnect_RequestDataOnSimObjectType( - self.handle, - request_id, - define_id, - radius_in_meters, - object_type, - ) == 0 - } - } - - pub unsafe fn set_data_on_sim_object( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - object_id: SIMCONNECT_OBJECT_ID, - flags: SIMCONNECT_DATA_SET_FLAG, - array_count: DWORD, - size: DWORD, - pntr: *mut std::os::raw::c_void, - ) -> bool { - unsafe { - SimConnect_SetDataOnSimObject( - self.handle, define_id, object_id, flags, array_count, size, pntr, - ) == 0 - } - } - - // ==================== Client Data ==================== - - pub fn create_client_data( - &self, - data_id: SIMCONNECT_CLIENT_DATA_ID, - size: DWORD, - flags: SIMCONNECT_CREATE_CLIENT_DATA_FLAG, - ) -> bool { - unsafe { SimConnect_CreateClientData(self.handle, data_id, size, flags) == 0 } - } - - pub fn map_client_data_name_to_id( - &self, - client_data_name: &str, - data_id: SIMCONNECT_CLIENT_DATA_ID, - ) -> bool { - let name = cstring(client_data_name); - unsafe { - SimConnect_MapClientDataNameToID(self.handle, name.as_ptr(), data_id) == 0 - } - } - - pub fn add_to_client_data_definition( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - offset: DWORD, - size_or_type: DWORD, - epsilon: f32, - datum_id: DWORD, - ) -> bool { - unsafe { - SimConnect_AddToClientDataDefinition( - self.handle, define_id, offset, size_or_type, epsilon, datum_id, - ) == 0 - } - } - - pub fn clear_client_data_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID) -> bool { - unsafe { SimConnect_ClearClientDataDefinition(self.handle, define_id) == 0 } - } - - pub fn request_client_data( - &self, - data_id: SIMCONNECT_CLIENT_DATA_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - period: SIMCONNECT_CLIENT_DATA_PERIOD, - flags: SIMCONNECT_CLIENT_DATA_REQUEST_FLAG, - origin: DWORD, - interval: DWORD, - limit: DWORD, - ) -> bool { - unsafe { - SimConnect_RequestClientData( - self.handle, - data_id, - request_id, - define_id, - period, - flags, - origin, - interval, - limit, - ) == 0 - } - } - - pub unsafe fn set_client_data( - &self, - data_id: SIMCONNECT_CLIENT_DATA_ID, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - flags: DWORD, - reserved: DWORD, - unit_size: DWORD, - data_set: *mut std::os::raw::c_void, - ) -> bool { - unsafe { - SimConnect_SetClientData( - self.handle, data_id, define_id, flags, reserved, unit_size, data_set, - ) == 0 - } - } - - // ==================== AI Objects ==================== - - pub fn ai_create_parked_atc_aircraft( - &self, - container_title: &str, - tail_number: &str, - airport_id: &str, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - let title = cstring(container_title); - let tail = cstring(tail_number); - let airport = cstring(airport_id); - - unsafe { - SimConnect_AICreateParkedATCAircraft( - self.handle, - title.as_ptr(), - tail.as_ptr(), - airport.as_ptr(), - request_id, - ) == 0 - } - } - - pub fn ai_create_enroute_atc_aircraft( - &self, - container_title: &str, - tail_number: &str, - flight_number: i32, - flight_plan_path: &str, - flight_plan_position: f64, - touch_and_go: bool, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - let title = cstring(container_title); - let tail = cstring(tail_number); - let plan = cstring(flight_plan_path); - - unsafe { - SimConnect_AICreateEnrouteATCAircraft( - self.handle, - title.as_ptr(), - tail.as_ptr(), - flight_number, - plan.as_ptr(), - flight_plan_position, - touch_and_go as i32, - request_id, - ) == 0 - } - } - - pub fn ai_create_non_atc_aircraft( - &self, - container_title: &str, - tail_number: &str, - init_pos: SIMCONNECT_DATA_INITPOSITION, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - let title = cstring(container_title); - let tail = cstring(tail_number); - - unsafe { - SimConnect_AICreateNonATCAircraft( - self.handle, title.as_ptr(), tail.as_ptr(), init_pos, request_id, - ) == 0 - } - } - - pub fn ai_create_simulated_object( - &self, - container_title: &str, - init_pos: SIMCONNECT_DATA_INITPOSITION, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - let title = cstring(container_title); - unsafe { - SimConnect_AICreateSimulatedObject(self.handle, title.as_ptr(), init_pos, request_id) == 0 - } - } - - pub fn ai_release_control( - &self, - object_id: SIMCONNECT_OBJECT_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { SimConnect_AIReleaseControl(self.handle, object_id, request_id) == 0 } - } - - pub fn ai_remove_object( - &self, - object_id: SIMCONNECT_OBJECT_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { SimConnect_AIRemoveObject(self.handle, object_id, request_id) == 0 } - } - - pub fn ai_set_aircraft_flight_plan( - &self, - object_id: SIMCONNECT_OBJECT_ID, - flight_plan_path: &str, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - let plan = cstring(flight_plan_path); - unsafe { - SimConnect_AISetAircraftFlightPlan( - self.handle, object_id, plan.as_ptr(), request_id, - ) == 0 - } - } - - // ==================== Weather ==================== - - pub fn weather_request_interpolated_observation( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - lat: f32, - lon: f32, - alt: f32, - ) -> bool { - unsafe { - SimConnect_WeatherRequestInterpolatedObservation(self.handle, request_id, lat, lon, alt) == 0 - } - } - - pub fn weather_request_observation_at_station( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - station: &str, - ) -> bool { - let station = cstring(station); - unsafe { - SimConnect_WeatherRequestObservationAtStation(self.handle, request_id, station.as_ptr()) == 0 - } - } - - pub fn weather_request_observation_at_nearest_station( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - lat: f32, - lon: f32, - ) -> bool { - unsafe { - SimConnect_WeatherRequestObservationAtNearestStation(self.handle, request_id, lat, lon) == 0 - } - } - - pub fn weather_create_station( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - icao: &str, - name: &str, - lat: f32, - lon: f32, - alt: f32, - ) -> bool { - let icao_c = cstring(icao); - let name_c = cstring(name); - - unsafe { - SimConnect_WeatherCreateStation( - self.handle, - request_id, - icao_c.as_ptr(), - name_c.as_ptr(), - lat, - lon, - alt, - ) == 0 - } - } - - pub fn weather_remove_station(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, station: &str) -> bool { - let station = cstring(station); - unsafe { - SimConnect_WeatherRemoveStation(self.handle, request_id, station.as_ptr()) == 0 - } - } - - pub fn weather_set_observation(&self, seconds: DWORD, observation: &str) -> bool { - let obs = cstring(observation); - unsafe { - SimConnect_WeatherSetObservation(self.handle, seconds, obs.as_ptr()) == 0 - } - } - - pub fn weather_set_mode_server(&self, port: DWORD, seconds: DWORD) -> bool { - unsafe { SimConnect_WeatherSetModeServer(self.handle, port, seconds) == 0 } - } - - pub fn weather_set_mode_theme(&self, theme_name: &str) -> bool { - let theme = cstring(theme_name); - unsafe { SimConnect_WeatherSetModeTheme(self.handle, theme.as_ptr()) == 0 } - } - - pub fn weather_set_mode_global(&self) -> bool { - unsafe { SimConnect_WeatherSetModeGlobal(self.handle) == 0 } - } - - pub fn weather_set_mode_custom(&self) -> bool { - unsafe { SimConnect_WeatherSetModeCustom(self.handle) == 0 } - } - - pub fn weather_set_dynamic_update_rate(&self, rate: DWORD) -> bool { - unsafe { SimConnect_WeatherSetDynamicUpdateRate(self.handle, rate) == 0 } - } - - pub fn weather_request_cloud_state( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - min_x: f32, - min_y: f32, - min_z: f32, - max_x: f32, - max_y: f32, - max_z: f32, - flags: DWORD, - ) -> bool { - unsafe { - SimConnect_WeatherRequestCloudState( - self.handle, request_id, min_x, min_y, min_z, max_x, max_y, max_z, flags, - ) == 0 - } - } - - pub fn weather_create_thermal( - &self, - request_id: SIMCONNECT_DATA_REQUEST_ID, - lat: f32, - lon: f32, - alt: f32, - radius: f32, - height: f32, - core_rate: f32, - core_turbulence: f32, - sink_rate: f32, - sink_turbulence: f32, - core_size: f32, - core_transition_size: f32, - sink_layer_size: f32, - sink_transition_size: f32, - ) -> bool { - unsafe { - SimConnect_WeatherCreateThermal( - self.handle, - request_id, - lat, - lon, - alt, - radius, - height, - core_rate, - core_turbulence, - sink_rate, - sink_turbulence, - core_size, - core_transition_size, - sink_layer_size, - sink_transition_size, - ) == 0 - } - } - - pub fn weather_remove_thermal(&self, object_id: SIMCONNECT_OBJECT_ID) -> bool { - unsafe { SimConnect_WeatherRemoveThermal(self.handle, object_id) == 0 } - } - - // ==================== Mission & System ==================== - - pub fn execute_mission_action(&self, instance_id: GUID) -> bool { - unsafe { SimConnect_ExecuteMissionAction(self.handle, instance_id) == 0 } - } - - pub fn complete_custom_mission_action(&self, instance_id: GUID) -> bool { - unsafe { SimConnect_CompleteCustomMissionAction(self.handle, instance_id) == 0 } - } - - pub fn request_system_state(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, state: &str) -> bool { - let state = cstring(state); - unsafe { SimConnect_RequestSystemState(self.handle, request_id, state.as_ptr()) == 0 } - } - - pub fn set_system_state(&self, state: &str, integer: DWORD, float_val: f32, string_val: &str) -> bool { - let state_c = cstring(state); - let string_c = cstring(string_val); - - unsafe { - SimConnect_SetSystemState( - self.handle, - state_c.as_ptr(), - integer, - float_val, - string_c.as_ptr(), - ) == 0 - } - } - - pub fn flight_load(&self, file_name: &str) -> bool { - let name = cstring(file_name); - unsafe { SimConnect_FlightLoad(self.handle, name.as_ptr()) == 0 } - } - - pub fn flight_save(&self, file_name: &str, title: &str, description: &str, flags: DWORD) -> bool { - let name = cstring(file_name); - let t = cstring(title); - let d = cstring(description); - unsafe { SimConnect_FlightSave(self.handle, name.as_ptr(), t.as_ptr(), d.as_ptr(), flags) == 0 } - } - - pub fn flight_plan_load(&self, file_name: &str) -> bool { - let name = cstring(file_name); - unsafe { SimConnect_FlightPlanLoad(self.handle, name.as_ptr()) == 0 } - } - - // ==================== Facilities ==================== - - pub fn subscribe_to_facilities( - &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { SimConnect_SubscribeToFacilities(self.handle, list_type, request_id) == 0 } - } - - pub fn unsubscribe_to_facilities(&self, list_type: SIMCONNECT_FACILITY_LIST_TYPE) -> bool { - unsafe { SimConnect_UnsubscribeToFacilities(self.handle, list_type) == 0 } - } - - pub fn request_facilities_list( - &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { SimConnect_RequestFacilitiesList(self.handle, list_type, request_id) == 0 } - } - - pub fn add_to_facility_definition(&self, define_id: SIMCONNECT_DATA_DEFINITION_ID, field_name: &str) -> bool { - let field = cstring(field_name); - unsafe { SimConnect_AddToFacilityDefinition(self.handle, define_id, field.as_ptr()) == 0 } - } - - pub fn request_facility_data( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - icao: &str, - region: Option<&str>, - ) -> bool { - let icao = cstring(icao); - let region = region.map(|s| cstring(s)); - unsafe { - SimConnect_RequestFacilityData( - self.handle, - define_id, - request_id, - icao.as_ptr(), - region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - ) == 0 - } - } - - pub fn subscribe_to_facilities_ex1( - &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, - new_in_range_request_id: SIMCONNECT_DATA_REQUEST_ID, - old_out_of_range_request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { - SimConnect_SubscribeToFacilities_EX1( - self.handle, - list_type, - new_in_range_request_id, - old_out_of_range_request_id, - ) == 0 - } - } - - pub fn unsubscribe_to_facilities_ex1( - &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, - unsubscribe_new_in_range: bool, - unsubscribe_old_out_of_range: bool, - ) -> bool { - unsafe { - SimConnect_UnsubscribeToFacilities_EX1( - self.handle, - list_type, - unsubscribe_new_in_range, - unsubscribe_old_out_of_range, - ) == 0 - } - } - - pub fn request_facilities_list_ex1( - &self, - list_type: SIMCONNECT_FACILITY_LIST_TYPE, - request_id: SIMCONNECT_DATA_REQUEST_ID, - ) -> bool { - unsafe { - SimConnect_RequestFacilitiesList_EX1(self.handle, list_type, request_id) == 0 - } - } - - pub fn request_facility_data_ex1( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - request_id: SIMCONNECT_DATA_REQUEST_ID, - icao: &str, - region: Option<&str>, - type_: Option, - ) -> bool { - let icao = cstring(icao); - let region = region.map(|s| cstring(s)); - unsafe { - SimConnect_RequestFacilityData_EX1( - self.handle, - define_id, - request_id, - icao.as_ptr(), - region.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - type_.unwrap_or(0) as ::std::os::raw::c_char, - ) == 0 - } - } - - pub unsafe fn request_jetway_data( - &self, - airport_icao: &str, - array_count: DWORD, - indexes: *mut i32, - ) -> bool { - let icao = cstring(airport_icao); - unsafe { - SimConnect_RequestJetwayData(self.handle, icao.as_ptr(), array_count, indexes) == 0 - } - } - - pub fn add_facility_data_definition_filter( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - filter_path: &str, - filter_data: *const std::os::raw::c_void, - cb_unit_size: DWORD, - ) -> bool { - let path = cstring(filter_path); - unsafe { - SimConnect_AddFacilityDataDefinitionFilter( - self.handle, - define_id, - path.as_ptr(), - cb_unit_size, - filter_data as *mut _, - ) == 0 - } - } - - pub fn clear_all_facility_data_definition_filters( - &self, - define_id: SIMCONNECT_DATA_DEFINITION_ID, - ) -> bool { - unsafe { - SimConnect_ClearAllFacilityDataDefinitionFilters(self.handle, define_id) == 0 - } - } - - // ==================== Camera ==================== - - pub fn camera_set_relative_6dof( - &self, - delta_x: f32, - delta_y: f32, - delta_z: f32, - pitch: f32, - bank: f32, - heading: f32, - ) -> bool { - unsafe { - SimConnect_CameraSetRelative6DOF( - self.handle, delta_x, delta_y, delta_z, pitch, bank, heading, - ) == 0 - } - } - - // ==================== Menu ==================== - - pub fn menu_add_item( - &self, - menu_item: &str, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - data: DWORD, - ) -> bool { - let item = cstring(menu_item); - unsafe { SimConnect_MenuAddItem(self.handle, item.as_ptr(), event_id, data) == 0 } - } - - pub fn menu_add_sub_item( - &self, - menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, - menu_item: &str, - sub_menu_event_id: SIMCONNECT_CLIENT_EVENT_ID, - data: DWORD, - ) -> bool { - let item = cstring(menu_item); - unsafe { - SimConnect_MenuAddSubItem(self.handle, menu_event_id, item.as_ptr(), sub_menu_event_id, data) == 0 - } - } - - pub fn menu_delete_item(&self, event_id: SIMCONNECT_CLIENT_EVENT_ID) -> bool { - unsafe { SimConnect_MenuDeleteItem(self.handle, event_id) == 0 } - } - - pub fn menu_delete_sub_item( - &self, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - sub_event_id: SIMCONNECT_CLIENT_EVENT_ID, - ) -> bool { - unsafe { SimConnect_MenuDeleteSubItem(self.handle, event_id, sub_event_id) == 0 } - } - - // ==================== Other ==================== - - pub fn enumerate_controllers(&self) -> bool { - unsafe { SimConnect_EnumerateControllers(self.handle) == 0 } - } - - pub fn enumerate_input_events(&self, request_id: SIMCONNECT_DATA_REQUEST_ID) -> bool { - unsafe { SimConnect_EnumerateInputEvents(self.handle, request_id) == 0 } - } - - pub fn get_input_event(&self, request_id: SIMCONNECT_DATA_REQUEST_ID, hash: u64) -> bool { - unsafe { SimConnect_GetInputEvent(self.handle, request_id, hash) == 0 } - } - - pub unsafe fn set_input_event( - &self, - hash: u64, - unit_size: DWORD, - value: *mut std::os::raw::c_void, - ) -> bool { - unsafe { SimConnect_SetInputEvent(self.handle, hash, unit_size, value) == 0 } - } - - pub fn subscribe_input_event(&self, hash: u64) -> bool { - unsafe { SimConnect_SubscribeInputEvent(self.handle, hash) == 0 } - } - - pub fn unsubscribe_input_event(&self, hash: u64) -> bool { - unsafe { SimConnect_UnsubscribeInputEvent(self.handle, hash) == 0 } - } - - pub fn enumerate_input_event_params(&self, hash: u64) -> bool { - unsafe { SimConnect_EnumerateInputEventParams(self.handle, hash) == 0 } - } - - pub unsafe fn execute_action( - &self, - request_id: DWORD, - action_id: &str, - unit_size: DWORD, - param_values: *mut std::os::raw::c_void, - ) -> bool { - let action = cstring(action_id); - unsafe { - SimConnect_ExecuteAction(self.handle, request_id, action.as_ptr(), unit_size, param_values) == 0 - } - } - - pub unsafe fn text( - &self, - text_type: SIMCONNECT_TEXT_TYPE, - time_in_seconds: f32, - event_id: SIMCONNECT_CLIENT_EVENT_ID, - unit_size: DWORD, - data_set: *mut std::os::raw::c_void, - ) -> bool { - unsafe { - SimConnect_Text(self.handle, text_type, time_in_seconds, event_id, unit_size, data_set) == 0 - } - } - - pub unsafe fn get_last_sent_packet_id(&self, error: *mut DWORD) -> bool { - unsafe { SimConnect_GetLastSentPacketID(self.handle, error) == 0 } - } - - pub unsafe fn call_dispatch( - &self, - dispatch_callback: DispatchProc, - context: *mut std::os::raw::c_void, - ) -> bool { - unsafe { SimConnect_CallDispatch(self.handle, dispatch_callback, context) == 0 } - } - - pub unsafe fn request_response_times(&self, count: DWORD, elapsed_seconds: *mut f32) -> bool { - unsafe { SimConnect_RequestResponseTimes(self.handle, count, elapsed_seconds) == 0 } - } - - // ==================== String Utilities ==================== - - pub unsafe fn retrieve_string( - p_data: *mut SIMCONNECT_RECV, - cb_data: DWORD, - p_string_v: *mut std::os::raw::c_void, - psz_string: *mut *mut std::os::raw::c_char, - pcb_string: *mut DWORD, - ) -> bool { - unsafe { - SimConnect_RetrieveString(p_data, cb_data, p_string_v, psz_string, pcb_string) == 0 - } - } - - pub unsafe fn insert_string( - p_dest: *mut std::os::raw::c_char, - cb_dest: DWORD, - pp_end: *mut *mut std::os::raw::c_void, - pcb_string: *mut DWORD, - p_source: *const std::os::raw::c_char, - ) -> bool { - unsafe { - SimConnect_InsertString(p_dest, cb_dest, pp_end, pcb_string, p_source) == 0 - } - } - - // ==================== Main Message Loop ==================== - - pub fn get_next_message(&self) -> Result, &str> { - unsafe { - let mut data_buf: *mut SIMCONNECT_RECV = ptr::null_mut(); - let mut size_buf: DWORD = 0; - - if SimConnect_GetNextDispatch(self.handle, &mut data_buf, &mut size_buf) != 0 { - return Err("Failed getting data from SimConnect"); - } - - if data_buf.is_null() { - return Ok(DispatchResult::Null); - } - - match (*data_buf).dwID as SIMCONNECT_RECV_ID { - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => Ok(DispatchResult::Null), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => Ok(DispatchResult::Exception(&*(data_buf as *const SIMCONNECT_RECV_EXCEPTION))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Ok(DispatchResult::Open(&*(data_buf as *const SIMCONNECT_RECV_OPEN))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Ok(DispatchResult::Quit(&*(data_buf as *const SIMCONNECT_RECV_QUIT))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => Ok(DispatchResult::Event(&*(data_buf as *const SIMCONNECT_RECV_EVENT))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE => Ok(DispatchResult::EventObjectAddRemove(&*(data_buf as *const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FILENAME => Ok(DispatchResult::EventFilename(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FILENAME))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_FRAME => Ok(DispatchResult::EventFrame(&*(data_buf as *const SIMCONNECT_RECV_EVENT_FRAME))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => Ok(DispatchResult::SimObjectData(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE => Ok(DispatchResult::SimObjectDataByType(&*(data_buf as *const SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WEATHER_OBSERVATION => Ok(DispatchResult::WeatherObservation(&*(data_buf as *const SIMCONNECT_RECV_WEATHER_OBSERVATION))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLOUD_STATE => Ok(DispatchResult::CloudState(&*(data_buf as *const SIMCONNECT_RECV_CLOUD_STATE))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID => Ok(DispatchResult::AssignedObjectId(&*(data_buf as *const SIMCONNECT_RECV_ASSIGNED_OBJECT_ID))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_RESERVED_KEY => Ok(DispatchResult::ReservedKey(&*(data_buf as *const SIMCONNECT_RECV_RESERVED_KEY))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CUSTOM_ACTION => Ok(DispatchResult::CustomAction(&*(data_buf as *const SIMCONNECT_RECV_CUSTOM_ACTION))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SYSTEM_STATE => Ok(DispatchResult::SystemState(&*(data_buf as *const SIMCONNECT_RECV_SYSTEM_STATE))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CLIENT_DATA => Ok(DispatchResult::ClientData(&*(data_buf as *const SIMCONNECT_RECV_CLIENT_DATA))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE => Ok(DispatchResult::EventWeatherMode(&*(data_buf as *const SIMCONNECT_RECV_EVENT_WEATHER_MODE))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => Ok(DispatchResult::AirportList(&*(data_buf as *const SIMCONNECT_RECV_AIRPORT_LIST))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_VOR_LIST => Ok(DispatchResult::VorList(&*(data_buf as *const SIMCONNECT_RECV_VOR_LIST))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NDB_LIST => Ok(DispatchResult::NdbList(&*(data_buf as *const SIMCONNECT_RECV_NDB_LIST))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_WAYPOINT_LIST => Ok(DispatchResult::WaypointList(&*(data_buf as *const SIMCONNECT_RECV_WAYPOINT_LIST))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED => Ok(DispatchResult::EventMultiplayerServerStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED => Ok(DispatchResult::EventMultiplayerClientStarted(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED => Ok(DispatchResult::EventMultiplayerSessionEnded(&*(data_buf as *const SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_END => Ok(DispatchResult::EventRaceEnd(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_END))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_RACE_LAP => Ok(DispatchResult::EventRaceLap(&*(data_buf as *const SIMCONNECT_RECV_EVENT_RACE_LAP))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT_EX1 => Ok(DispatchResult::EventEx1(&*(data_buf as *const SIMCONNECT_RECV_EVENT_EX1))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA => Ok(DispatchResult::FacilityData(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_DATA_END => Ok(DispatchResult::FacilityDataEnd(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_DATA_END))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_FACILITY_MINIMAL_LIST => Ok(DispatchResult::FacilityMinimalList(&*(data_buf as *const SIMCONNECT_RECV_FACILITY_MINIMAL_LIST))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_JETWAY_DATA => Ok(DispatchResult::JetwayData(&*(data_buf as *const SIMCONNECT_RECV_JETWAY_DATA))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ACTION_CALLBACK => Ok(DispatchResult::ActionCallback(&*(data_buf as *const SIMCONNECT_RECV_ACTION_CALLBACK))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENTS => Ok(DispatchResult::EnumerateInputEvents(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENTS))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_GET_INPUT_EVENT => Ok(DispatchResult::GetInputEvent(&*(data_buf as *const SIMCONNECT_RECV_GET_INPUT_EVENT))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SUBSCRIBE_INPUT_EVENT => Ok(DispatchResult::SubscribeInputEvent(&*(data_buf as *const SIMCONNECT_RECV_SUBSCRIBE_INPUT_EVENT))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_ENUMERATE_INPUT_EVENT_PARAMS => Ok(DispatchResult::EnumerateInputEventParams(&*(data_buf as *const SIMCONNECT_RECV_ENUMERATE_INPUT_EVENT_PARAMS))), - SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_CONTROLLERS_LIST => Ok(DispatchResult::ControllersList(&*(data_buf as *const SIMCONNECT_RECV_CONTROLLERS_LIST))), - _ => Err("Unhandled RECV_ID"), - } - } - } -} - -impl Drop for SimConnector { - fn drop(&mut self) { - if !self.handle.is_null() { - let _ = self.close(); - } - } -} - -#[inline] -fn cstring(s: &str) -> CString { - CString::new(s).expect("string contained interior nul byte") -} \ No newline at end of file +#[cfg(feature = "fs2024")] +pub use simconnect_fs2024 as fs2024;