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/Readme.md b/Readme.md index c960e92..70d97c7 100644 --- a/Readme.md +++ b/Readme.md @@ -2,10 +2,18 @@ # SimConnect Bindings for Rust +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) + + ## Requirements -- [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)) +- [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 @@ -16,14 +24,18 @@ Add this to your `Cargo.toml` simconnect = "0.4" ``` +_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 +43,13 @@ 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 +## 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. diff --git a/SimConnect.dll b/SimConnect.dll index 2aa284c..8f0fe28 100644 Binary files a/SimConnect.dll and b/SimConnect.dll differ 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/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() { 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