diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8f7cbc3..21be411 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,23 +19,18 @@ jobs: steps: - name: Install latest nightly - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@nightly with: - toolchain: nightly - override: true components: rustfmt, clippy - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Build run: cargo build --verbose - name: Clippy check - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features + run: cargo clippy --all-features -- -D warnings - name: Style check run: cargo fmt -- --check diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index baa1f62..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,2281 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" - -[[package]] -name = "ahash" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957" -dependencies = [ - "getrandom 0.2.0", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" -dependencies = [ - "memchr", -] - -[[package]] -name = "android_log-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e" - -[[package]] -name = "android_log-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" - -[[package]] -name = "android_logger" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cbd542dd180566fad88fd2729a53a62a734843c626638006a9d63ec0688484e" -dependencies = [ - "android_log-sys 0.1.2", - "env_logger", - "lazy_static", - "log", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "anyhow" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" - -[[package]] -name = "anymap" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" - -[[package]] -name = "async-channel" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d373d78ded7d0b3fa8039375718cde0aace493f2e34fb60f51cbf567562ca801" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "vec-arena", -] - -[[package]] -name = "async-task" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "base-x" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "bevy" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b14f8ba7c373fdf7bd27547bb95f2849b2569bf02bbf3d19ca54e9d692de4f" -dependencies = [ - "bevy_internal", - "syn", -] - -[[package]] -name = "bevy_app" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "845be45f00d9c031071f8c68f7681bf791796634efa5f58937275337154cb019" -dependencies = [ - "bevy_derive", - "bevy_ecs", - "bevy_reflect", - "bevy_utils", - "serde", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "bevy_asset" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426b3557161b34230e7ec04bdc48664509985ca7a6b874491f238eadd1e7cab0" -dependencies = [ - "anyhow", - "bevy_app", - "bevy_diagnostic", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "crossbeam-channel 0.5.1", - "downcast-rs", - "js-sys", - "ndk-glue", - "notify", - "parking_lot", - "rand 0.8.3", - "ron", - "serde", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "bevy_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa5b6d7f68752cfb5b498fc5ea9ad5cfb5de871cdd4d894f2e046fef2e2898ea" -dependencies = [ - "bevy_app", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", -] - -[[package]] -name = "bevy_derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6fd06d325cfb4998b26fc84476380611ce6a2d0a8a99b501328c79d7bda104" -dependencies = [ - "Inflector", - "find-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "bevy_diagnostic" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933425d2febac4a8aadc8aed05ddac2d5891c91ae60dd191b24a6e093dcbeba" -dependencies = [ - "bevy_app", - "bevy_core", - "bevy_ecs", - "bevy_log", - "bevy_utils", - "parking_lot", -] - -[[package]] -name = "bevy_ecs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf4745460111bd4285ed6c3e6caa4d882db95471edb02b88c6ad4eac89b923c" -dependencies = [ - "async-channel", - "bevy_ecs_macros", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bitflags", - "downcast-rs", - "fixedbitset", - "fxhash", - "parking_lot", - "rand 0.8.3", - "serde", - "thiserror", -] - -[[package]] -name = "bevy_ecs_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65323f6896068407b768c16ec1aa5c8891d49a28b725d0cbabc663d7f47baaec" -dependencies = [ - "find-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "bevy_input" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91a3a768c59a5965f491cda74fd75a72b4cd7c51c85b5a731dd4d8688582dc5" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_utils", -] - -[[package]] -name = "bevy_internal" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c568981b2911567cba7f6dae7190bac295ffd411bca777edb1b5152b1ccd62" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_scene", - "bevy_tasks", - "bevy_transform", - "bevy_utils", - "bevy_window", - "ndk-glue", -] - -[[package]] -name = "bevy_log" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae100fe4e6fc8f7bbf28c121cda0ced7ab79088374beb7ab8be39120603beb18" -dependencies = [ - "android_log-sys 0.2.0", - "bevy_app", - "bevy_utils", - "console_error_panic_hook", - "tracing-subscriber", - "tracing-wasm", -] - -[[package]] -name = "bevy_math" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb36a879cdc96f554b62dd7c7c02392a9a10e94082e4bc686a8242e1d674e7cc" -dependencies = [ - "bevy_reflect", - "glam", -] - -[[package]] -name = "bevy_reflect" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7f57646077e9b016f079e0f39fe2826dce407bb0dccc29b481a33ef7552847" -dependencies = [ - "bevy_reflect_derive", - "bevy_utils", - "downcast-rs", - "erased-serde", - "glam", - "parking_lot", - "serde", - "smallvec", - "thiserror", -] - -[[package]] -name = "bevy_reflect_derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc3f45d1d49c6e984b492ee13564677d1392828cac50c030e025f74f69386e1" -dependencies = [ - "find-crate", - "proc-macro2", - "quote", - "syn", - "uuid", -] - -[[package]] -name = "bevy_scene" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1eaa680e61749cc226bcdcd0d968c396fe52c2a4e9e1718422888953ba6c3b" -dependencies = [ - "anyhow", - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_reflect", - "bevy_transform", - "bevy_utils", - "parking_lot", - "ron", - "serde", - "thiserror", - "uuid", -] - -[[package]] -name = "bevy_tasks" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77243565dde30ce01e538c615db54bc939a36e4c468b271e86a980004bac7bc9" -dependencies = [ - "async-channel", - "async-executor", - "event-listener", - "futures-lite", - "instant", - "num_cpus", - "wasm-bindgen-futures", -] - -[[package]] -name = "bevy_transform" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d166fe11f67dc195b42207e7b096f36680f611afc8f4105b3d81865b66ecf91" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_utils", - "smallvec", -] - -[[package]] -name = "bevy_utils" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c384a69b670329f968f59abdcf6506f183cf18b8619d6ec1cbfe33e268e5da20" -dependencies = [ - "ahash", - "getrandom 0.2.0", - "instant", - "tracing", - "uuid", -] - -[[package]] -name = "bevy_window" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96496cb0a9c79ca6744a25e69edff4ba363c14b6070897a66a597db208405f0" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_utils", - "web-sys", -] - -[[package]] -name = "bincode" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" -dependencies = [ - "byteorder", - "serde", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bumpalo" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - -[[package]] -name = "cc" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi 0.3.9", -] - -[[package]] -name = "client" -version = "0.1.0" -dependencies = [ - "chrono", - "fern", - "hook", - "imgui", - "imgui-sys", - "log", - "once_cell", - "shared", - "winapi 0.3.9", - "winreg", -] - -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" -dependencies = [ - "cfg-if 0.1.10", - "wasm-bindgen", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" - -[[package]] -name = "cpp" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4875a08600be48dcc9cb6ee07f104a3e0752e95184dede6a30044d6480bf50e8" -dependencies = [ - "cpp_macros", -] - -[[package]] -name = "cpp_build" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762705b71f4a8c5b65148de0e76bf18770c724ca2759f04ca29be9d508e1230d" -dependencies = [ - "cc", - "cpp_common", - "lazy_static", - "proc-macro2", - "regex", - "syn", - "unicode-xid", -] - -[[package]] -name = "cpp_common" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df78ad28e5fe814285016779fb3d3b874520c799a847e6190bf2b834cc4ff283" -dependencies = [ - "lazy_static", - "proc-macro2", - "syn", -] - -[[package]] -name = "cpp_macros" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f93a21e618c10abc84ebb63ffa5952e1f7a4568b8141d542d5ef860e4a8fc25" -dependencies = [ - "aho-corasick", - "byteorder", - "cpp_common", - "if_rust_version", - "lazy_static", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" -dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils 0.8.4", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "derivative" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "erased-serde" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca8b296792113e1500fd935ae487be6e00ce318952a6880555554824d6ebf38" -dependencies = [ - "serde", -] - -[[package]] -name = "event-listener" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" - -[[package]] -name = "fastrand" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" -dependencies = [ - "instant", -] - -[[package]] -name = "fern" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065" -dependencies = [ - "log", -] - -[[package]] -name = "filetime" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "redox_syscall", - "winapi 0.3.9", -] - -[[package]] -name = "find-crate" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a1d48e8ff33649ee2d7c510b79ecf1f8a52b684d446a72de600ad7e2823b6" -dependencies = [ - "toml", -] - -[[package]] -name = "fixedbitset" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "fsevent" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f347202c95c98805c216f9e1df210e8ebaec9fdb2365700a43c10797a35e63" -dependencies = [ - "bitflags", - "fsevent-sys", -] - -[[package]] -name = "fsevent-sys" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a29c77f1ca394c3e73a9a5d24cfcabb734682d9634fc398f2204a63c994120" -dependencies = [ - "libc", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures-core" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b" - -[[package]] -name = "futures-io" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c" - -[[package]] -name = "futures-lite" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381a7ad57b1bad34693f63f6f377e1abded7a9c85c9d3eb6771e11c60aaadab9" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.1.10", - "waker-fn", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generator" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cdc09201b2e8ca1b19290cf7e65de2246b8e91fb6874279722189c4de7b94dc" -dependencies = [ - "cc", - "libc", - "log", - "rustc_version", - "winapi 0.3.9", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "stdweb", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "glam" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70155b56080764b8b758e91e4c63d06da0262c0c939f2cd991cd1382087147df" -dependencies = [ - "serde", - "spirv-std", -] - -[[package]] -name = "hermit-abi" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" -dependencies = [ - "libc", -] - -[[package]] -name = "hook" -version = "0.1.0" -dependencies = [ - "cpp", - "cpp_build", - "keycodes", - "log", - "once_cell", - "retour", - "winapi 0.3.9", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "if_rust_version" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46dbcb333e86939721589d25a3557e180b52778cb33c7fdfe9e0158ff790d5ec" - -[[package]] -name = "imgui" -version = "0.6.0" -source = "git+https://github.com/Cryma/imgui-rs#0e7a852b7a4e92912670e28bb14b0e062aa0e322" -dependencies = [ - "bitflags", - "imgui-sys", - "lazy_static", - "parking_lot", -] - -[[package]] -name = "imgui-sys" -version = "0.6.0" -source = "git+https://github.com/Cryma/imgui-rs#0e7a852b7a4e92912670e28bb14b0e062aa0e322" -dependencies = [ - "cc", -] - -[[package]] -name = "inotify" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46dd0a94b393c730779ccfd2a872b67b1eb67be3fc33082e733bdb38b5fde4d4" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" -dependencies = [ - "cfg-if 0.1.10", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "itoa" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "js-sys" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "keycodes" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a9f5ede1b60d265d3230a5007a142f2171d76612e1511b3c46673a8f7d5bfb" - -[[package]] -name = "launcher" -version = "0.1.0" -dependencies = [ - "sysinfo", - "winapi 0.3.9", - "winreg", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" - -[[package]] -name = "libudis86-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139bbf9ddb1bfc90c1ac64dd2923d9c957cd433cee7315c018125d72ab08a6b0" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "lock_api" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "loom" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" -dependencies = [ - "cfg-if 0.1.10", - "generator", - "scoped-tls", - "serde", - "serde_json", -] - -[[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - -[[package]] -name = "matchers" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" - -[[package]] -name = "memoffset" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mio" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "mmap-fixed-fixed" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0681853891801e4763dc252e843672faf32bcfee27a0aa3b19733902af450acc" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "ndk" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" -dependencies = [ - "jni-sys", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-glue" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" -dependencies = [ - "android_logger", - "lazy_static", - "libc", - "log", - "ndk", - "ndk-macro", - "ndk-sys", -] - -[[package]] -name = "ndk-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" - -[[package]] -name = "net2" -version = "0.2.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "notify" -version = "5.0.0-pre.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d03607cf88b4b160ba0e9ed425fff3cee3b55ac813f0c685b3a3772da37d0e" -dependencies = [ - "anymap", - "bitflags", - "crossbeam-channel 0.4.4", - "filetime", - "fsevent", - "fsevent-sys", - "inotify", - "libc", - "mio", - "mio-extras", - "walkdir", - "winapi 0.3.9", -] - -[[package]] -name = "ntapi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "num-integer" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" -dependencies = [ - "derivative", - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95" - -[[package]] -name = "pin-project-lite" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.15", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - -[[package]] -name = "rand" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" -dependencies = [ - "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.2", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.15", -] - -[[package]] -name = "rand_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" -dependencies = [ - "getrandom 0.2.0", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core 0.6.2", -] - -[[package]] -name = "rayon" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" -dependencies = [ - "crossbeam-channel 0.5.1", - "crossbeam-deque", - "crossbeam-utils 0.8.4", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "regex" -version = "1.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-automata" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" - -[[package]] -name = "region" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" -dependencies = [ - "bitflags", - "libc", - "mach2", - "windows-sys", -] - -[[package]] -name = "retour" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9af44d40e2400b44d491bfaf8eae111b09f23ac4de6e92728e79d93e699c527" -dependencies = [ - "cfg-if 1.0.0", - "generic-array", - "libc", - "libudis86-sys", - "mmap-fixed-fixed", - "once_cell", - "region", - "slice-pool2", -] - -[[package]] -name = "ron" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a58080b7bb83b2ea28c3b7a9a994fd5e310330b7c8ca5258d99b98128ecfe4" -dependencies = [ - "base64", - "bitflags", - "serde", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "server" -version = "0.1.0" -dependencies = [ - "chrono", - "fern", - "log", - "once_cell", - "shared", -] - -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - -[[package]] -name = "sharded-slab" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4921be914e16899a80adefb821f8ddb7974e3f1250223575a44ed994882127" -dependencies = [ - "lazy_static", - "loom", -] - -[[package]] -name = "shared" -version = "0.1.0" -dependencies = [ - "bevy", - "bincode", - "log", - "serde", -] - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" - -[[package]] -name = "slice-pool2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3d689654af89bdfeba29a914ab6ac0236d382eb3b764f7454dde052f2821f8" - -[[package]] -name = "smallvec" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" -dependencies = [ - "serde", -] - -[[package]] -name = "spirv-std" -version = "0.4.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726c4c71ff802a9754ffae31c04c4d867aa23b49f883a56202dce285066ad792" -dependencies = [ - "bitflags", - "num-traits", - "spirv-std-macros", - "spirv-types", -] - -[[package]] -name = "spirv-std-macros" -version = "0.4.0-alpha.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789e03eacd37ed496c7648bb7866a5ed6ae8959bf222bfde4c8afc23e28de7c6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "spirv-types" -version = "0.4.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7f880a5540c04261e7454b5f3a342b5540283911ca9ebfec83eba9fb607ca0" - -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "syn" -version = "1.0.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "sysinfo" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f5e4b56d92c7c56cc8a06df0cc06860a8ec6102e9a8a5ee85dff90afbeadf3d" -dependencies = [ - "cfg-if 1.0.0", - "core-foundation-sys", - "doc-comment", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi 0.3.9", -] - -[[package]] -name = "thiserror" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - -[[package]] -name = "toml" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645" -dependencies = [ - "serde", -] - -[[package]] -name = "tracing" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite 0.2.0", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-log" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-serde" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401" -dependencies = [ - "ansi_term", - "chrono", - "lazy_static", - "matchers", - "regex", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", - "tracing-serde", -] - -[[package]] -name = "tracing-wasm" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae741706df70547fca8715f74a8569677666e7be3454313af70f6e158034485" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "uuid" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -dependencies = [ - "rand 0.7.3", - "serde", -] - -[[package]] -name = "vec-arena" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" - -[[package]] -name = "version_check" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasm-bindgen" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" -dependencies = [ - "cfg-if 0.1.10", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" -dependencies = [ - "cfg-if 0.1.10", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" - -[[package]] -name = "web-sys" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winreg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d107f8c6e916235c4c01cabb3e8acf7bea8ef6a63ca2e7fa0527c049badfc48c" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] diff --git a/Cargo.toml b/Cargo.toml index 4c00517..1406b02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,4 @@ [workspace] -members = [ - "client", - "hook", - "launcher", - "server", - "shared", -] - +members = ["client", "hook", "launcher", "server", "shared"] default-members = ["launcher"] +resolver = "2" diff --git a/client/Cargo.lock b/client/Cargo.lock deleted file mode 100644 index 733b4ab..0000000 --- a/client/Cargo.lock +++ /dev/null @@ -1,316 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "aho-corasick" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" -dependencies = [ - "memchr", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "cc" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cpp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd679e3b11fc72f93b851f8f72b227deb004613fa637ea700a1ef348aecf1f" -dependencies = [ - "cpp_macros", -] - -[[package]] -name = "cpp_build" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afdf675ccc9cc6aff408febf02e08584b6b948178624b4da5cc562a78273d3f" -dependencies = [ - "cc", - "cpp_common", - "lazy_static", - "proc-macro2", - "regex", - "syn", - "unicode-xid", -] - -[[package]] -name = "cpp_common" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7145e26dfba4419500ae901a641b7486fb84ee365967f26f5d8c1069ececa9bf" -dependencies = [ - "lazy_static", - "proc-macro2", - "syn", -] - -[[package]] -name = "cpp_macros" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b14cbed7d9b15f03be8d38438595d2547df5001e2a22b7e59812a3fade09e4" -dependencies = [ - "aho-corasick", - "byteorder", - "cpp_common", - "if_rust_version", - "lazy_static", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "cryv-hook" -version = "0.1.0" -dependencies = [ - "cpp", - "cpp_build", - "detour", - "process-memory", - "winapi 0.3.9", -] - -[[package]] -name = "detour" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078595bac2ff1822ae53ae3ca1c1ffca97897ecc959adf0137152bfdc278d0d3" -dependencies = [ - "cfg-if", - "generic-array", - "lazy_static", - "libc", - "libudis86-sys", - "mmap-fixed", - "region", - "slice-pool", -] - -[[package]] -name = "generic-array" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" -dependencies = [ - "typenum", -] - -[[package]] -name = "if_rust_version" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46dbcb333e86939721589d25a3557e180b52778cb33c7fdfe9e0158ff790d5ec" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" - -[[package]] -name = "libudis86-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139bbf9ddb1bfc90c1ac64dd2923d9c957cd433cee7315c018125d72ab08a6b0" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" - -[[package]] -name = "mmap-fixed" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c1ae264d6343d3b4079549f6bc9e6d074dc4106cb1324c7753c6ce11d07b21" -dependencies = [ - "kernel32-sys", - "libc", - "winapi 0.2.8", -] - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "process-memory" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61d7c67e1d5e7e8e100ce1240b08e3a7249fe7d02b04232f006f8f60f27791fe" -dependencies = [ - "libc", - "mach", - "winapi 0.3.9", -] - -[[package]] -name = "quote" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-syntax" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" - -[[package]] -name = "region" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" -dependencies = [ - "bitflags", - "libc", - "mach", - "winapi 0.3.9", -] - -[[package]] -name = "slice-pool" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733fc6e5f1bd3a8136f842c9bdea4e5f17c910c2fcc98c90c3aa7604ef5e2e7a" - -[[package]] -name = "syn" -version = "1.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/client/Cargo.toml b/client/Cargo.toml index e769902..3fc79d2 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -2,19 +2,20 @@ name = "client" version = "0.1.0" authors = ["Alexander Serdyuk "] -edition = "2018" +edition = "2024" [lib] crate-type = ["cdylib"] [dependencies] -chrono = "0.4.19" -fern = "0.6.0" +chrono = "0.4" +fern = "0.6" +glam = "0.29" +hecs = "0.10" hook = { path = "../hook" } -imgui = { git = "https://github.com/Cryma/imgui-rs" } -imgui-sys = { git = "https://github.com/Cryma/imgui-rs" } -log = "0.4.14" -once_cell = "1.7.2" +log = "0.4" +serde_json = "1.0" shared = { path = "../shared" } +tungstenite = "0.24" winapi = "0.3" -winreg = "0.8.0" +winreg = "0.52" diff --git a/client/src/cleanup.rs b/client/src/cleanup.rs index cab5260..3a043a7 100644 --- a/client/src/cleanup.rs +++ b/client/src/cleanup.rs @@ -1,17 +1,6 @@ use crate::{entities::EntityHandle, wrapped_natives::entities::delete_entity}; use hook::natives::*; use log::{debug, error}; -use shared::bevy::prelude::*; - -pub struct CleanupPlugin; -impl Plugin for CleanupPlugin { - fn build(&self, app: &mut AppBuilder) { - app.add_startup_system(startup_system.exclusive_system()) - .add_system(cleanup_tick_system.exclusive_system()) - .add_system(cleanup_system.exclusive_system()) - .add_system(hijack_frontend_menu.exclusive_system()); - } -} #[derive(Copy, Clone, Debug, PartialEq)] enum EntityCleanupType { @@ -25,7 +14,7 @@ pub struct EntityCleanupData { last_run_at: std::time::SystemTime, } -pub fn startup_system(world: &mut World) { +pub fn startup_system(world: &mut hecs::World) { let player_ped_id = player::player_ped_id(); entity::set_entity_coords_no_offset(player_ped_id, 412.4, -976.71, 29.43, false, false, false); @@ -49,15 +38,15 @@ pub fn startup_system(world: &mut World) { misc::terminate_all_scripts_with_this_name(&gameplay_script_cstring); } - world.spawn().insert(EntityCleanupData { + world.spawn((EntityCleanupData { cleanup_type: EntityCleanupType::Ped, last_run_at: std::time::SystemTime::UNIX_EPOCH, - }); + },)); - world.spawn().insert(EntityCleanupData { + world.spawn((EntityCleanupData { cleanup_type: EntityCleanupType::Vehicle, last_run_at: std::time::SystemTime::UNIX_EPOCH, - }); + },)); } pub fn cleanup_tick_system() { @@ -96,36 +85,38 @@ pub fn cleanup_tick_system() { pad::disable_control_action(0, 243, true); // INPUT_ENTER_CHEAT_CODE } -pub fn cleanup_system(world: &mut World) { - let mut existing_entities = Vec::::new(); - - { - let mut entities = world.query::<&EntityHandle>(); - for entity in entities.iter(world) { - existing_entities.push(entity.clone()); - } - } - - let mut entity_cleanup_data = world.query::<&mut EntityCleanupData>(); +pub fn cleanup_system(world: &mut hecs::World) { + let existing_entities: Vec = world + .query::<&EntityHandle>() + .iter() + .map(|(_, handle)| *handle) + .collect(); let now = std::time::SystemTime::now(); - for mut data in entity_cleanup_data.iter_mut(world) { + let cleanup_entries: Vec<(hecs::Entity, EntityCleanupData)> = world + .query::<&EntityCleanupData>() + .iter() + .map(|(id, data)| (id, *data)) + .collect(); + + for (entity_id, mut data) in cleanup_entries { match now.duration_since(data.last_run_at) { Ok(duration) => { if duration.as_millis() < 500 { - return; + continue; } - data.last_run_at = now; + if let Ok(mut entry) = world.get::<&mut EntityCleanupData>(entity_id) { + *entry = data; + } } Err(error) => { error!( "Error while running entity cleanup for type {:?}: {}", data.cleanup_type, error ); - - return; + continue; } } @@ -136,23 +127,18 @@ pub fn cleanup_system(world: &mut World) { let mut deleted_entities = 0; - for mut entity in entities { - // Don't try to delete the own player ped or non-existing entities - if player::player_ped_id() == entity || entity::does_entity_exist(entity) == false { + for mut game_entity in entities { + if player::player_ped_id() == game_entity || !entity::does_entity_exist(game_entity) { continue; } - let should_entity_exist = (&mut existing_entities) - .iter() - .find(|x| x.handle == entity) - .is_some(); + let should_exist = existing_entities.iter().any(|x| x.handle == game_entity); - if should_entity_exist { + if should_exist { continue; } - delete_entity(&mut entity); - + delete_entity(&mut game_entity); deleted_entities += 1; } @@ -165,7 +151,7 @@ pub fn cleanup_system(world: &mut World) { } } -pub fn hijack_frontend_menu(_world: &mut World) { +pub fn hijack_frontend_menu() { pad::disable_control_action(0, 199, true); pad::disable_control_action(0, 200, true); @@ -180,7 +166,7 @@ pub fn hijack_frontend_menu(_world: &mut World) { } } -static GAMEPLAY_SCRIPTS: [&'static str; 748] = [ +static GAMEPLAY_SCRIPTS: [&str; 748] = [ "abigail1", "abigail2", "achievement_controller", diff --git a/client/src/entities.rs b/client/src/entities.rs index 0076206..f5cea84 100644 --- a/client/src/entities.rs +++ b/client/src/entities.rs @@ -1,7 +1,7 @@ use crate::utility::StreamedModel; +use glam::Vec3; use hook::natives::{entity, misc, vehicle}; use hook::types::NativeVector3; -use shared::bevy::math::Vec3; use shared::{EntityModel, EntityTransform}; #[derive(Copy, Clone, Debug, PartialEq)] @@ -32,7 +32,6 @@ pub fn get_entity_transform(entity_id: i32) -> EntityTransform { pub fn get_entity_model(entity_id: i32) -> EntityModel { let model = entity::get_entity_model(entity_id); - EntityModel { model } } diff --git a/client/src/imgui.rs b/client/src/imgui.rs deleted file mode 100644 index 302381d..0000000 --- a/client/src/imgui.rs +++ /dev/null @@ -1,309 +0,0 @@ -use std::sync::{atomic::AtomicBool, Mutex}; - -use once_cell::sync::{Lazy, OnceCell}; -use shared::bevy::prelude::Entity; -use winapi::{ - shared::minwindef::LPARAM, shared::minwindef::UINT, shared::minwindef::WPARAM, - shared::windef::HWND, um::winuser::FindWindowA, -}; - -use crate::{entities::EntityHandle, wrapped_natives::entities}; - -static mut SHOW_CURSOR: AtomicBool = AtomicBool::new(false); -static LOG_BUFFER: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); - -static mut CTX: OnceCell> = OnceCell::new(); -static mut IMGUI_DATA: OnceCell = OnceCell::new(); - -#[derive(Debug)] -struct ContextWrapper { - pub ctx: imgui::Context, -} - -#[derive(Debug)] -struct ImguiData { - pub show_commands: bool, - pub show_logs: bool, - pub vehicle_model: imgui::ImString, - pub primary_color: i32, - pub secondary_color: i32, -} - -impl Default for ImguiData { - fn default() -> Self { - ImguiData { - show_commands: false, - show_logs: false, - vehicle_model: imgui::ImString::with_capacity(32), - primary_color: 112, - secondary_color: 112, - } - } -} - -unsafe impl Send for ContextWrapper {} - -fn get_context( - device: *mut hook::winapi::um::d3d11::ID3D11Device, - context: *mut hook::winapi::um::d3d11::ID3D11DeviceContext, -) -> &'static Mutex { - unsafe { - CTX.get_or_init(|| { - let window_name = std::ffi::CString::new("grcWindow").unwrap(); - let window = FindWindowA(window_name.as_ptr(), std::ptr::null()); - - let ctx = imgui::Context::create(); - - imgui_sys::ImGui_ImplDX11_Init( - device as *mut imgui_sys::ID3D11Device, - context as *mut imgui_sys::ID3D11DeviceContext, - ); - imgui_sys::ImGui_ImplWin32_Init(window as *mut std::ffi::c_void); - - add_log("Initialized D3D11_PRESENT hook"); - - Mutex::new(ContextWrapper { ctx }) - }) - } -} - -fn get_data<'a>() -> &'a mut ImguiData { - unsafe { - if let None = IMGUI_DATA.get() { - IMGUI_DATA.set(ImguiData::default()).unwrap(); - } - - IMGUI_DATA.get_mut().unwrap() - } -} - -pub(super) fn d3d11_present( - device: *mut hook::winapi::um::d3d11::ID3D11Device, - context: *mut hook::winapi::um::d3d11::ID3D11DeviceContext, -) { - let mut wrapper = get_context(device, context).lock().unwrap(); - let data = get_data(); - - unsafe { - imgui_sys::ImGui_ImplDX11_NewFrame(); - imgui_sys::ImGui_ImplWin32_NewFrame(); - }; - - let ui = wrapper.ctx.frame(); - - draw(&ui, data); - - unsafe { - (*imgui_sys::igGetIO()).MouseDrawCursor = *SHOW_CURSOR.get_mut(); - let draw_data = ui.render() as *const imgui::DrawData; - imgui_sys::ImGui_ImplDX11_RenderDrawData( - (draw_data as *const std::ffi::c_void) as *mut std::ffi::c_void, - ); - }; -} - -fn draw(ui: &imgui::Ui, data: &mut ImguiData) { - ui.main_menu_bar(|| { - ui.menu(imgui::im_str!("CryV"), true, || {}); - - ui.menu(imgui::im_str!("Windows"), true, || { - if imgui::MenuItem::new(imgui::im_str!("Commands")) - .selected(data.show_commands) - .build(&ui) - { - data.show_commands = !data.show_commands; - } - - if imgui::MenuItem::new(imgui::im_str!("Logs")) - .selected(data.show_logs) - .build(&ui) - { - data.show_logs = !data.show_logs; - } - }); - }); - - if data.show_commands { - imgui::Window::new(imgui::im_str!("Commands")) - .size([300.0, 100.0], imgui::Condition::FirstUseEver) - .build(&ui, || { - if ui.button(imgui::im_str!("Spawn Vehicle"), [0.0, 0.0]) { - ui.open_popup(imgui::im_str!("Spawn Vehicle")); - } - - ui.same_line_with_spacing(0.0, -1.0); - - if ui.button(imgui::im_str!("Delete Vehicle"), [0.0, 0.0]) { - crate::thread_jumper::run(Box::new(|world| { - let player_ped_id = hook::natives::player::player_ped_id(); - let is_in_vehicle = - hook::natives::ped::is_ped_in_any_vehicle(player_ped_id, false); - - if is_in_vehicle == false { - add_log("You are not in any vehicle"); - - return; - } - - let mut vehicle_id = - hook::natives::ped::get_vehicle_ped_is_in(player_ped_id, false); - // Copy the vehicle id, as GTA5 will clear the current one, after deleting the entity - let vehicle_id_copy = vehicle_id.clone(); - - entities::delete_entity(&mut vehicle_id); - - let mut existing_entities = world.query::<(Entity, &EntityHandle)>(); - - let mut found_entity: Option = None; - - for (entity, entity_data) in existing_entities.iter(world) { - if entity_data.handle != vehicle_id_copy { - continue; - } - - found_entity = Some(entity); - } - - if let Some(x) = found_entity { - world.despawn(x); - - add_log("Vehicle has been deleted"); - } - })); - } - - if ui.button(imgui::im_str!("Load Cayo Perico"), [0.0, 0.0]) { - crate::thread_jumper::run(Box::new(|_| { - let heist_island_cstring = std::ffi::CString::new("HeistIsland").unwrap(); - hook::natives::streaming::_set_island_hopper_enabled( - &heist_island_cstring, - true, - ); - })); - } - - ui.same_line_with_spacing(0.0, -1.0); - - if ui.button(imgui::im_str!("Unload Cayo Perico"), [0.0, 0.0]) { - crate::thread_jumper::run(Box::new(|_| { - let x = std::ffi::CString::new("HeistIsland").unwrap(); - hook::natives::streaming::_set_island_hopper_enabled(&x, false); - })); - } - - if ui.button(imgui::im_str!("Teleport to Cayo Perico"), [0.0, 0.0]) { - crate::thread_jumper::run(Box::new(|_| { - let player_ped = hook::natives::player::player_ped_id(); - - hook::natives::entity::set_entity_coords_no_offset( - player_ped, 4840.571, -5174.425, 2.0, false, false, false, - ); - })); - } - - ui.popup_modal(imgui::im_str!("Spawn Vehicle")) - .always_auto_resize(true) - .build(|| { - ui.input_text(imgui::im_str!("Vehicle Model"), &mut data.vehicle_model) - .build(); - - ui.input_int(imgui::im_str!("Primary Color"), &mut data.primary_color) - .build(); - - ui.input_int(imgui::im_str!("Secondary Color"), &mut data.secondary_color) - .build(); - - ui.separator(); - - if ui.button(imgui::im_str!("Done"), [120.0, 0.0]) { - let model_name = data.vehicle_model.to_string(); - let primary_color = data.primary_color; - let secondary_color = data.secondary_color; - - crate::thread_jumper::run(Box::new(move |world| { - let player_ped_id = hook::natives::player::player_ped_id(); - let position = - hook::natives::entity::get_entity_coords(player_ped_id, true); - let rotation = - hook::natives::entity::get_entity_rotation(player_ped_id, 2); - - let (handle, model, transform, vehicle) = - crate::entities::create_vehicle_with_model_name( - &model_name, - position, - rotation, - primary_color, - secondary_color, - ); - - hook::natives::ped::set_ped_into_vehicle( - player_ped_id, - handle.handle, - -1, - ); - - world - .spawn() - .insert_bundle((handle, model, transform, vehicle)); - - add_log(&format!( - "Spawned vehicle ({})", - model_name.to_uppercase() - )); - })); - - ui.close_current_popup(); - } - }); - }); - } - - if data.show_logs { - imgui::Window::new(imgui::im_str!("Logs")) - .size([300.0, 100.0], imgui::Condition::FirstUseEver) - .build(&ui, || { - let buffer = LOG_BUFFER.lock().unwrap(); - ui.text(imgui::ImString::new(buffer.join("\n"))); - }); - } -} - -pub(super) fn wndproc(hwnd: HWND, message: UINT, w_param: WPARAM, l_param: LPARAM) { - unsafe { - if *SHOW_CURSOR.get_mut() == false { - return; - } - - imgui_sys::ImGui_ImplWin32_WndProcHandler( - hwnd as *mut std::ffi::c_void, - message, - w_param as *mut u32, - l_param as i64, - ); - }; -} - -pub(super) fn handle_cursor() { - if hook::is_key_released(hook::keycodes::KEY_F1, true) { - unsafe { - SHOW_CURSOR = AtomicBool::new(*SHOW_CURSOR.get_mut() == false); - } - } - - if unsafe { *SHOW_CURSOR.get_mut() } { - hook::natives::pad::disable_all_control_actions(0); - } -} - -fn add_log(message: &str) { - let mut buffer = LOG_BUFFER.lock().unwrap(); - let time = chrono::Local::now(); - buffer.push( - format!( - "[{}] {}", - time.format("%Y-%m-%d %H:%M:%S"), - message.to_string() - ) - .to_string(), - ); -} diff --git a/client/src/lib.rs b/client/src/lib.rs index 7bbc9c2..c510e6f 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,85 +1,122 @@ -// TODO: Move imgui related code to separate crate and disallow unsafe code #![deny(unsafe_code)] -use log::info; -use once_cell::sync::Lazy; -use shared::bevy::{app::ScheduleRunnerPlugin, prelude::*}; +use log::{debug, info}; +use std::sync::LazyLock; use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey}; mod cleanup; mod entities; -#[allow(unsafe_code)] -mod imgui; +mod menu; +pub mod network; mod thread_jumper; mod ui; mod utility; mod wrapped_natives; -#[macro_export] -macro_rules! clone_query { - ($query:expr) => {{ - let mut items = Vec::new(); +static INSTALL_DIRECTORY: LazyLock = LazyLock::new(|| { + let key = RegKey::predef(HKEY_LOCAL_MACHINE) + .open_subkey(r"Software\Phantom") + .expect("Phantom registry key not found. Run the launcher first."); - for item in &mut $query.iter() { - items.push(item.clone()); - } - - items - }}; -} - -static INSTALL_DIRECTORY: &str = "D:\\Work\\Phantom-RS\\"; - -// static INSTALL_DIRECTORY: Lazy = Lazy::new(|| { -// let key = RegKey::predef(HKEY_LOCAL_MACHINE) -// .open_subkey(r"Software\CryV") -// .unwrap(); + let value: String = key + .get_value("InstallDirectory") + .expect("InstallDirectory registry value not found"); -// let value: String = key.get_value("InstallDirectory").unwrap(); - -// value -// }); + value +}); make_entrypoint!(entrypoint); fn entrypoint() { create_logger().expect("Something went wrong while creating the logger!"); - debug!("InstallDirectory: {}", INSTALL_DIRECTORY.to_owned()); + debug!("InstallDirectory: {}", *INSTALL_DIRECTORY); info!("--------------------------"); - info!("Starting CryV"); + info!("Starting Phantom Multiplayer"); hook::initialize(script_callback); - hook::register_present_callback(imgui::d3d11_present); - hook::register_window_proc_callback(imgui::wndproc); - - info!("Successfully started CryV"); + info!("Successfully started Phantom Multiplayer"); } -fn update_keyboard(_world: &mut World) { - hook::update_keyboard(); -} +fn script_callback() { + let mut world = hecs::World::new(); + let mut game_menu = menu::Menu::new(); + + // Startup systems (run once) + cleanup::startup_system(&mut world); + ui::ui_startup_system(&mut world); + + // Connect to the multiplayer server + let net = network::NetworkClient::connect_localhost("Player"); + + // Main loop + loop { + hook::update_keyboard(); + cleanup::cleanup_tick_system(); + cleanup::cleanup_system(&mut world); + cleanup::hijack_frontend_menu(); + + // Menu (F1 to toggle) + game_menu.update(&mut world); + + // Send player position to server each tick + if net.is_connected() { + let player_ped = hook::natives::player::player_ped_id(); + let pos = hook::natives::entity::get_entity_coords(player_ped, true); + let rot = hook::natives::entity::get_entity_rotation(player_ped, 2); + let vel = hook::natives::entity::get_entity_velocity(player_ped); + + net.send_player_update( + glam::Vec3::new(pos.x, pos.y, pos.z), + glam::Vec3::new(rot.x, rot.y, rot.z), + glam::Vec3::new(vel.x, vel.y, vel.z), + ); + } -fn script_wait(_world: &mut World) { - hook::script_wait(0); + // Process incoming server messages + for msg in net.poll_messages() { + handle_server_message(&msg); + } + + ui::draw_text_entries(&mut world); + thread_jumper::run_native_callbacks(&mut world); + hook::script_wait(0); + } } -fn script_callback() { - App::build() - .add_plugin(ScheduleRunnerPlugin::default()) - .add_system(update_keyboard.exclusive_system()) - .add_plugin(cleanup::CleanupPlugin) - .add_plugin(ui::UiPlugin) - .add_system(imgui::handle_cursor.exclusive_system()) - .add_system(script_wait.exclusive_system()) - .add_plugin(thread_jumper::ThreadJumperPlugin) - .run(); +fn handle_server_message(msg: &shared::ServerMessage) { + use shared::ServerMessage; + + match msg { + ServerMessage::Welcome { player_id } => { + info!("Connected to server! Player ID: {}", player_id); + } + ServerMessage::PlayerConnected { player_id, name } => { + info!("Player '{}' (ID: {}) connected", name, player_id); + } + ServerMessage::PlayerDisconnected { player_id } => { + info!("Player {} disconnected", player_id); + } + ServerMessage::PlayerUpdate { player_id, transform } => { + debug!( + "Player {} at ({:.1}, {:.1}, {:.1})", + player_id, transform.position.x, transform.position.y, transform.position.z + ); + } + ServerMessage::EntityUpdate { entity_id, transform, model } => { + debug!("Entity {} (model {}) updated", entity_id, model); + let _ = transform; + } + ServerMessage::ChatMessage { player_id, message } => { + info!("[Chat] Player {}: {}", player_id, message); + } + } } fn create_logger() -> Result<(), fern::InitError> { - let log_file_path = format!("{}/cryv.log", INSTALL_DIRECTORY.to_owned()); + let log_file_path = format!("{}/phantom.log", *INSTALL_DIRECTORY); fern::Dispatch::new() .format(|out, message, record| { diff --git a/client/src/menu.rs b/client/src/menu.rs new file mode 100644 index 0000000..8cddd52 --- /dev/null +++ b/client/src/menu.rs @@ -0,0 +1,274 @@ +use crate::wrapped_natives::{entities as entity_helpers, ui as ui_native}; +use hook::natives::*; +use log::info; + +const MENU_X: f32 = 0.15; +const MENU_Y_START: f32 = 0.3; +const MENU_WIDTH: f32 = 0.22; +const ITEM_HEIGHT: f32 = 0.04; +const TITLE_HEIGHT: f32 = 0.05; +const TEXT_SCALE: f32 = 0.35; + +const BG_COLOR: (i32, i32, i32, i32) = (10, 10, 10, 200); +const TITLE_COLOR: (i32, i32, i32, i32) = (100, 50, 200, 230); +const SELECTED_COLOR: (i32, i32, i32, i32) = (80, 40, 160, 200); +const TEXT_COLOR: (i32, i32, i32, i32) = (255, 255, 255, 255); +const TEXT_SELECTED_COLOR: (i32, i32, i32, i32) = (255, 255, 100, 255); + +static VEHICLE_MODELS: &[&str] = &[ + "adder", "zentorno", "t20", "osiris", "turismor", "entityxf", "cheetah", + "infernus", "bullet", "vacca", "voltic", "comet2", "elegy2", "sultanrs", + "kuruma", "insurgent", "hydra", "buzzard", "rhino", "dump", +]; + +pub struct Menu { + pub open: bool, + selected: usize, + page: MenuPage, +} + +#[derive(Clone, Copy, PartialEq)] +enum MenuPage { + Main, + SpawnVehicle, +} + +struct MenuEntry { + label: &'static str, +} + +impl Menu { + pub fn new() -> Self { + Menu { + open: false, + selected: 0, + page: MenuPage::Main, + } + } + + pub fn update(&mut self, world: &mut hecs::World) { + // F1 toggles menu + if hook::is_key_released(hook::keycodes::KEY_F1, true) { + self.open = !self.open; + if self.open { + self.page = MenuPage::Main; + self.selected = 0; + } + } + + if !self.open { + return; + } + + // Disable game input while menu is open + pad::disable_all_control_actions(0); + + let item_count = self.current_items().len(); + + // Navigate + if hook::is_key_released(hook::keycodes::KEY_UP, true) && self.selected > 0 { + self.selected -= 1; + } + if hook::is_key_released(hook::keycodes::KEY_DOWN, true) && self.selected + 1 < item_count + { + self.selected += 1; + } + + // Back + if hook::is_key_released(hook::keycodes::KEY_BACKSPACE, true) { + if self.page != MenuPage::Main { + self.page = MenuPage::Main; + self.selected = 0; + } else { + self.open = false; + } + return; + } + + // Select + if hook::is_key_released(hook::keycodes::KEY_RETURN, true) { + self.execute_selected(world); + } + + self.draw(); + } + + fn current_items(&self) -> Vec { + match self.page { + MenuPage::Main => vec![ + MenuEntry { label: "Spawn Vehicle >" }, + MenuEntry { label: "Delete Current Vehicle" }, + MenuEntry { label: "Load Cayo Perico" }, + MenuEntry { label: "Unload Cayo Perico" }, + MenuEntry { label: "Teleport to Cayo Perico" }, + ], + MenuPage::SpawnVehicle => VEHICLE_MODELS + .iter() + .map(|m| MenuEntry { label: m }) + .collect(), + } + } + + fn execute_selected(&mut self, world: &mut hecs::World) { + match self.page { + MenuPage::Main => match self.selected { + 0 => { + self.page = MenuPage::SpawnVehicle; + self.selected = 0; + } + 1 => delete_current_vehicle(world), + 2 => set_cayo_perico(true), + 3 => set_cayo_perico(false), + 4 => teleport_cayo_perico(), + _ => {} + }, + MenuPage::SpawnVehicle => { + if self.selected < VEHICLE_MODELS.len() { + spawn_vehicle(world, VEHICLE_MODELS[self.selected]); + } + } + } + } + + fn draw(&self) { + let items = self.current_items(); + let total_height = TITLE_HEIGHT + (items.len() as f32 * ITEM_HEIGHT) + 0.01; + + let title = match self.page { + MenuPage::Main => "Phantom", + MenuPage::SpawnVehicle => "Spawn Vehicle", + }; + + // Title background + graphics::draw_rect( + MENU_X, + MENU_Y_START, + MENU_WIDTH, + TITLE_HEIGHT, + TITLE_COLOR.0, + TITLE_COLOR.1, + TITLE_COLOR.2, + TITLE_COLOR.3, + ); + + // Title text + ui_native::draw_text( + title, + MENU_X - MENU_WIDTH / 2.0 + 0.01, + MENU_Y_START - TITLE_HEIGHT / 2.0 + 0.005, + TEXT_SCALE + 0.05, + TEXT_COLOR, + false, + MENU_X + MENU_WIDTH / 2.0, + ); + + // Items background + let items_bg_y = MENU_Y_START + TITLE_HEIGHT / 2.0 + (items.len() as f32 * ITEM_HEIGHT) / 2.0; + graphics::draw_rect( + MENU_X, + items_bg_y, + MENU_WIDTH, + items.len() as f32 * ITEM_HEIGHT + 0.01, + BG_COLOR.0, + BG_COLOR.1, + BG_COLOR.2, + BG_COLOR.3, + ); + + // Draw items + for (i, item) in items.iter().enumerate() { + let y = MENU_Y_START + TITLE_HEIGHT / 2.0 + (i as f32 * ITEM_HEIGHT) + 0.005; + let is_selected = i == self.selected; + + if is_selected { + graphics::draw_rect( + MENU_X, + y + ITEM_HEIGHT / 2.0, + MENU_WIDTH, + ITEM_HEIGHT, + SELECTED_COLOR.0, + SELECTED_COLOR.1, + SELECTED_COLOR.2, + SELECTED_COLOR.3, + ); + } + + let color = if is_selected { TEXT_SELECTED_COLOR } else { TEXT_COLOR }; + + ui_native::draw_text( + item.label, + MENU_X - MENU_WIDTH / 2.0 + 0.01, + y, + TEXT_SCALE, + color, + false, + MENU_X + MENU_WIDTH / 2.0, + ); + } + + // Footer hint + let footer_y = MENU_Y_START + TITLE_HEIGHT / 2.0 + (items.len() as f32 * ITEM_HEIGHT) + 0.01; + ui_native::draw_text( + "Enter: Select | Backspace: Back | F1: Close", + MENU_X - MENU_WIDTH / 2.0 + 0.005, + footer_y, + 0.25, + (180, 180, 180, 200), + false, + MENU_X + MENU_WIDTH / 2.0, + ); + } +} + +fn spawn_vehicle(world: &mut hecs::World, model_name: &str) { + let player_ped_id = player::player_ped_id(); + let position = entity::get_entity_coords(player_ped_id, true); + let rotation = entity::get_entity_rotation(player_ped_id, 2); + + let (handle, model, transform, vehicle_data) = + crate::entities::create_vehicle_with_model_name(model_name, position, rotation, 112, 112); + + ped::set_ped_into_vehicle(player_ped_id, handle.handle, -1); + world.spawn((handle, model, transform, vehicle_data)); + + info!("Spawned vehicle: {}", model_name.to_uppercase()); +} + +fn delete_current_vehicle(world: &mut hecs::World) { + let player_ped_id = player::player_ped_id(); + + if !ped::is_ped_in_any_vehicle(player_ped_id, false) { + return; + } + + let mut vehicle_id = ped::get_vehicle_ped_is_in(player_ped_id, false); + let vehicle_id_copy = vehicle_id; + + entity_helpers::delete_entity(&mut vehicle_id); + + let found: Option = world + .query::<&crate::entities::EntityHandle>() + .iter() + .find(|(_, h)| h.handle == vehicle_id_copy) + .map(|(e, _)| e); + + if let Some(entity) = found { + let _ = world.despawn(entity); + info!("Deleted vehicle"); + } +} + +fn set_cayo_perico(enable: bool) { + let name = std::ffi::CString::new("HeistIsland").unwrap(); + streaming::_set_island_hopper_enabled(&name, enable); + info!( + "Cayo Perico {}", + if enable { "loaded" } else { "unloaded" } + ); +} + +fn teleport_cayo_perico() { + let player_ped = player::player_ped_id(); + entity::set_entity_coords_no_offset(player_ped, 4840.571, -5174.425, 2.0, false, false, false); + info!("Teleported to Cayo Perico"); +} diff --git a/client/src/network.rs b/client/src/network.rs new file mode 100644 index 0000000..7790641 --- /dev/null +++ b/client/src/network.rs @@ -0,0 +1,237 @@ +use glam::Vec3; +use log::{error, info, warn}; +use shared::{ClientMessage, EntityTransform, ServerMessage}; +use std::sync::mpsc::{Receiver, Sender, TryRecvError}; +use std::sync::{Arc, Mutex}; +use tungstenite::{Message, WebSocket, stream::MaybeTlsStream}; +use std::net::TcpStream; + +const DEFAULT_SERVER_ADDR: &str = "ws://127.0.0.1:9770"; + +/// Handle to the network connection, used from the script thread. +pub struct NetworkClient { + outgoing_tx: Sender, + incoming_rx: Mutex>, + connected: Arc, + player_id: Arc>>, +} + +impl NetworkClient { + /// Spawn a background thread that connects to the server. + /// Returns immediately with a handle for sending/receiving messages. + pub fn connect(server_addr: &str, player_name: &str) -> Self { + let (outgoing_tx, outgoing_rx) = std::sync::mpsc::channel::(); + let (incoming_tx, incoming_rx) = std::sync::mpsc::channel::(); + let connected = Arc::new(std::sync::atomic::AtomicBool::new(false)); + let player_id = Arc::new(Mutex::new(None)); + + let addr = server_addr.to_string(); + let name = player_name.to_string(); + let connected_clone = connected.clone(); + let player_id_clone = player_id.clone(); + + std::thread::spawn(move || { + network_thread(addr, name, outgoing_rx, incoming_tx, connected_clone, player_id_clone); + }); + + NetworkClient { + outgoing_tx, + incoming_rx: Mutex::new(incoming_rx), + connected, + player_id, + } + } + + /// Connect to localhost with default port. + pub fn connect_localhost(player_name: &str) -> Self { + Self::connect(DEFAULT_SERVER_ADDR, player_name) + } + + /// Send the current player position to the server. + pub fn send_player_update(&self, position: Vec3, rotation: Vec3, velocity: Vec3) { + if !self.is_connected() { + return; + } + + let _ = self.outgoing_tx.send(ClientMessage::PlayerUpdate(EntityTransform { + position, + rotation, + velocity, + })); + } + + /// Send a chat message. + pub fn send_chat(&self, message: &str) { + if !self.is_connected() { + return; + } + let _ = self.outgoing_tx.send(ClientMessage::ChatMessage(message.to_string())); + } + + /// Drain all pending server messages. Call this each tick from the script thread. + pub fn poll_messages(&self) -> Vec { + let rx = self.incoming_rx.lock().unwrap(); + let mut messages = Vec::new(); + loop { + match rx.try_recv() { + Ok(msg) => messages.push(msg), + Err(TryRecvError::Empty) => break, + Err(TryRecvError::Disconnected) => { + self.connected.store(false, std::sync::atomic::Ordering::Relaxed); + break; + } + } + } + messages + } + + pub fn is_connected(&self) -> bool { + self.connected.load(std::sync::atomic::Ordering::Relaxed) + } + + pub fn player_id(&self) -> Option { + *self.player_id.lock().unwrap() + } +} + +fn network_thread( + addr: String, + player_name: String, + outgoing_rx: Receiver, + incoming_tx: Sender, + connected: Arc, + player_id: Arc>>, +) { + info!("Connecting to server at {}...", addr); + + let mut socket = match connect_with_retry(&addr, 5) { + Some(s) => s, + None => { + error!("Failed to connect to server at {} after retries", addr); + return; + } + }; + + connected.store(true, std::sync::atomic::Ordering::Relaxed); + info!("Connected to server at {}", addr); + + // Send connect message + let connect_msg = ClientMessage::Connect { name: player_name }; + if let Err(e) = send_message(&mut socket, &connect_msg) { + error!("Failed to send connect message: {}", e); + return; + } + + // Set socket to non-blocking so we can interleave reads and writes + if let MaybeTlsStream::Plain(ref tcp) = socket.get_ref() { + let _ = tcp.set_nonblocking(true); + } + + loop { + // Try to read incoming messages (non-blocking) + match socket.read() { + Ok(Message::Text(text)) => { + match serde_json::from_str::(&text) { + Ok(server_msg) => { + // Capture player_id from Welcome + if let ServerMessage::Welcome { player_id: pid } = &server_msg { + *player_id.lock().unwrap() = Some(*pid); + info!("Server assigned player ID: {}", pid); + } + if incoming_tx.send(server_msg).is_err() { + info!("Script thread dropped, closing network"); + break; + } + } + Err(e) => { + warn!("Invalid server message: {}", e); + } + } + } + Ok(Message::Close(_)) => { + info!("Server closed connection"); + break; + } + Err(tungstenite::Error::Io(ref e)) + if e.kind() == std::io::ErrorKind::WouldBlock => + { + // No data available, that's fine + } + Err(e) => { + error!("WebSocket read error: {}", e); + break; + } + _ => {} + } + + // Try to send outgoing messages + loop { + match outgoing_rx.try_recv() { + Ok(msg) => { + if let Err(e) = send_message(&mut socket, &msg) { + error!("Failed to send message: {}", e); + break; + } + } + Err(TryRecvError::Empty) => break, + Err(TryRecvError::Disconnected) => { + info!("Outgoing channel closed, shutting down network"); + let _ = send_message(&mut socket, &ClientMessage::Disconnect); + let _ = socket.close(None); + connected.store(false, std::sync::atomic::Ordering::Relaxed); + return; + } + } + } + + // Small sleep to avoid busy-spinning + std::thread::sleep(std::time::Duration::from_millis(16)); + } + + connected.store(false, std::sync::atomic::Ordering::Relaxed); + let _ = socket.close(None); + info!("Disconnected from server"); +} + +fn connect_with_retry( + addr: &str, + max_attempts: u32, +) -> Option>> { + for attempt in 1..=max_attempts { + match tungstenite::connect(addr) { + Ok((socket, _response)) => return Some(socket), + Err(e) => { + warn!( + "Connection attempt {}/{} failed: {}", + attempt, max_attempts, e + ); + if attempt < max_attempts { + std::thread::sleep(std::time::Duration::from_secs(2)); + } + } + } + } + None +} + +fn send_message( + socket: &mut WebSocket>, + msg: &ClientMessage, +) -> Result<(), tungstenite::Error> { + let json = serde_json::to_string(msg).map_err(|e| { + tungstenite::Error::Io(std::io::Error::new(std::io::ErrorKind::Other, e)) + })?; + + // Socket might be in non-blocking mode, temporarily set blocking for writes + if let MaybeTlsStream::Plain(ref tcp) = socket.get_ref() { + let _ = tcp.set_nonblocking(false); + } + + socket.send(Message::Text(json.into()))?; + + if let MaybeTlsStream::Plain(ref tcp) = socket.get_ref() { + let _ = tcp.set_nonblocking(true); + } + + Ok(()) +} diff --git a/client/src/thread_jumper.rs b/client/src/thread_jumper.rs index a350436..62cdb27 100644 --- a/client/src/thread_jumper.rs +++ b/client/src/thread_jumper.rs @@ -1,47 +1,10 @@ -use once_cell::sync::Lazy; -use shared::bevy::prelude::*; -use std::{collections::VecDeque, sync::Mutex}; +use std::sync::Mutex; -pub type NativeCallback = Box; +pub type NativeCallback = Box; -static NATIVE_CALLBACKS: Lazy>> = Lazy::new(|| Mutex::new(vec![])); +static NATIVE_CALLBACKS: Mutex> = Mutex::new(Vec::new()); -pub struct ThreadJumperData { - queue: VecDeque>, -} - -impl Default for ThreadJumperData { - fn default() -> Self { - ThreadJumperData { - queue: VecDeque::new(), - } - } -} - -impl<'a> ThreadJumperData { - pub fn invoke(&mut self, callback: impl Fn() + Send + Sync + 'static) { - self.queue.push_back(Box::new(callback)); - } - - fn work(&mut self) { - while let Some(callback) = self.queue.pop_front() { - callback(); - } - - self.queue.clear(); - } -} - -pub struct ThreadJumperPlugin; - -impl Plugin for ThreadJumperPlugin { - fn build(&self, app: &mut AppBuilder) { - app.init_resource::() - .add_system(run_native_callbacks.exclusive_system()); - } -} - -fn run_native_callbacks(world: &mut World) { +pub fn run_native_callbacks(world: &mut hecs::World) { let mut native_callbacks = NATIVE_CALLBACKS.lock().unwrap(); for callback in native_callbacks.as_slice() { @@ -49,17 +12,9 @@ fn run_native_callbacks(world: &mut World) { } native_callbacks.clear(); - - let thread_jumper_data = world.get_resource_mut::(); - - match thread_jumper_data { - Some(mut thread_jumper_data) => thread_jumper_data.work(), - None => log::error!("Could not fetch thread jumper data in run_native_callbacks system."), - } } pub fn run(callback: NativeCallback) { let mut callbacks = NATIVE_CALLBACKS.lock().unwrap(); - callbacks.push(callback); } diff --git a/client/src/ui.rs b/client/src/ui.rs index 5af55c4..029078b 100644 --- a/client/src/ui.rs +++ b/client/src/ui.rs @@ -1,13 +1,4 @@ use crate::wrapped_natives::*; -use shared::bevy::prelude::*; - -pub struct UiPlugin; -impl Plugin for UiPlugin { - fn build(&self, app: &mut AppBuilder) { - app.add_startup_system(ui_startup_system.exclusive_system()) - .add_system(draw_text_entries.exclusive_system()); - } -} #[derive(Clone, Debug, PartialEq)] pub struct TextEntry { @@ -18,20 +9,18 @@ pub struct TextEntry { color: (i32, i32, i32, i32), } -pub fn ui_startup_system(world: &mut World) { - world.spawn().insert(TextEntry { - text: "CryV".to_owned(), - pos_x: 0.975, +pub fn ui_startup_system(world: &mut hecs::World) { + world.spawn((TextEntry { + text: "Phantom".to_owned(), + pos_x: 0.96, pos_y: 0.01, scale: 0.42, color: (200, 200, 200, 255), - }); + },)); } -pub fn draw_text_entries(world: &mut World) { - let mut text_entries = world.query::<&TextEntry>(); - - for entry in text_entries.iter(world) { +pub fn draw_text_entries(world: &mut hecs::World) { + for (_, entry) in world.query::<&TextEntry>().iter() { ui::draw_text( &entry.text, entry.pos_x, diff --git a/hook/Cargo.toml b/hook/Cargo.toml index 464865e..7d0b7fc 100644 --- a/hook/Cargo.toml +++ b/hook/Cargo.toml @@ -2,16 +2,13 @@ name = "hook" version = "0.1.0" authors = ["Alexander Serdyuk "] -edition = "2018" +edition = "2024" build = "build.rs" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -cpp = "0.5.6" +cpp = "0.5.9" keycodes = "0.1.0" -log = "0.4.14" -once_cell = "1.7.2" +log = "0.4" winapi = { version = "0.3", features = ["libloaderapi", "memoryapi", "winbase", "timeapi", "dxgi", "d3d11", "winuser"] } retour = { version = "0.3", features = ["static-detour"] } diff --git a/hook/build.rs b/hook/build.rs index e7d2d0f..da1c8fe 100644 --- a/hook/build.rs +++ b/hook/build.rs @@ -1,5 +1,3 @@ -use cpp_build; - fn main() { cpp_build::build("src/lib.rs"); } diff --git a/hook/src/d3drenderer.rs b/hook/src/d3drenderer.rs index 55aeb2a..5a231d1 100644 --- a/hook/src/d3drenderer.rs +++ b/hook/src/d3drenderer.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_op_in_unsafe_fn)] + use cpp::cpp; use winapi::Interface; @@ -10,8 +12,6 @@ struct RendererData { device: Option<*mut winapi::um::d3d11::ID3D11Device>, context: Option<*mut winapi::um::d3d11::ID3D11DeviceContext>, present_callbacks: Vec, - // pre_resize_callbacks: Vec, - // post_resize_callbacks: Vec, } impl RendererData { @@ -19,8 +19,6 @@ impl RendererData { device: None, context: None, present_callbacks: Vec::new(), - // pre_resize_callbacks: Vec::new(), - // post_resize_callbacks: Vec::new(), }; } @@ -100,18 +98,6 @@ pub fn register_present_callback(callback: D3DCallback) { }; } -// pub fn register_pre_resize_callback(callback: D3DCallback) { -// unsafe { -// RENDERER_DATA.pre_resize_callbacks.push(callback); -// }; -// } - -// pub fn register_post_resize_callback(callback: D3DCallback) { -// unsafe { -// RENDERER_DATA.post_resize_callbacks.push(callback); -// }; -// } - pub(crate) fn present(swapchain: *mut winapi::shared::dxgi::IDXGISwapChain) { unsafe { let mut device: *mut std::ffi::c_void = std::ptr::null_mut(); @@ -136,22 +122,6 @@ pub(crate) fn present(swapchain: *mut winapi::shared::dxgi::IDXGISwapChain) { } } -// pub(crate) fn pre_resize() { -// unsafe { -// for callback in &RENDERER_DATA.pre_resize_callbacks { -// callback(); -// } -// } -// } - -// pub(crate) fn post_resize() { -// unsafe { -// for callback in &RENDERER_DATA.post_resize_callbacks { -// callback(); -// } -// } -// } - cpp! {{ #include diff --git a/hook/src/keyboard.rs b/hook/src/keyboard.rs index f8a9d61..5576913 100644 --- a/hook/src/keyboard.rs +++ b/hook/src/keyboard.rs @@ -1,6 +1,9 @@ -use std::{collections::HashMap, collections::VecDeque, sync::Mutex}; +#![allow(unsafe_op_in_unsafe_fn)] + +use std::collections::HashMap; +use std::collections::VecDeque; +use std::sync::{Mutex, OnceLock}; -use once_cell::sync::{Lazy, OnceCell}; use winapi::{ shared::minwindef::DWORD, shared::minwindef::LPARAM, shared::minwindef::LRESULT, shared::minwindef::UINT, shared::minwindef::WPARAM, shared::windef::HWND, @@ -10,6 +13,7 @@ use winapi::{ um::winuser::WM_KEYUP, um::winuser::WM_SYSKEYDOWN, um::winuser::WM_SYSKEYUP, um::winuser::WNDPROC, }; + #[derive(Copy, Clone, Debug)] pub struct KeyboardCallbackState { pub key: u8, @@ -43,24 +47,26 @@ const KEYS_SIZE: u8 = 255; const NOW_PERIOD: DWORD = 100; const MAX_DOWN: DWORD = 5000; -static KEY_STATES: Lazy>> = Lazy::new(|| { - let mut key_states: HashMap = HashMap::new(); - - for i in 0..KEYS_SIZE { - key_states.insert(i, KeyState::default()); - } - - Mutex::new(key_states) -}); - -static KEYBOAD_CALLBACKS: Lazy>> = Lazy::new(|| Mutex::new(vec![])); -static WINDOW_PROC_CALLBACKS: Lazy>> = - Lazy::new(|| Mutex::new(vec![])); -static QUEUED_STATES: Lazy>> = - Lazy::new(|| Mutex::new(VecDeque::new())); -static WNDPROC: OnceCell> = OnceCell::new(); +static KEY_STATES: OnceLock>> = OnceLock::new(); +static KEYBOARD_CALLBACKS: Mutex> = Mutex::new(Vec::new()); +static WINDOW_PROC_CALLBACKS: Mutex> = Mutex::new(Vec::new()); +static QUEUED_STATES: Mutex> = Mutex::new(VecDeque::new()); +static WNDPROC: OnceLock> = OnceLock::new(); + +fn key_states() -> &'static Mutex> { + KEY_STATES.get_or_init(|| { + let mut key_states: HashMap = HashMap::new(); + for i in 0..KEYS_SIZE { + key_states.insert(i, KeyState::default()); + } + Mutex::new(key_states) + }) +} pub fn initialize_keyboard_hook() { + // Ensure key states are initialized + key_states(); + let window_name = std::ffi::CString::new("grcWindow").unwrap(); let window = unsafe { FindWindowA(window_name.as_ptr(), std::ptr::null()) }; @@ -80,10 +86,10 @@ pub fn is_key_pressed(key: u8) -> bool { return false; } - let key_states = KEY_STATES.lock().unwrap(); + let key_states = key_states().lock().unwrap(); let key_state = key_states.get(&key).unwrap(); - return (unsafe { GetTickCount() } < key_state.time + MAX_DOWN) && key_state.is_up_now == false; + (unsafe { GetTickCount() } < key_state.time + MAX_DOWN) && !key_state.is_up_now } pub fn is_key_released(key: u8, exclusive: bool) -> bool { @@ -91,7 +97,7 @@ pub fn is_key_released(key: u8, exclusive: bool) -> bool { return false; } - let mut key_states = KEY_STATES.lock().unwrap(); + let mut key_states = key_states().lock().unwrap(); let key_state = key_states.get(&key).unwrap(); let is_released = @@ -105,24 +111,22 @@ pub fn is_key_released(key: u8, exclusive: bool) -> bool { } pub fn register_keyboard_callback(callback: KeyboardCallback) { - let mut keyboard_callbacks = KEYBOAD_CALLBACKS.lock().unwrap(); - + let mut keyboard_callbacks = KEYBOARD_CALLBACKS.lock().unwrap(); keyboard_callbacks.push(callback); } pub fn register_window_proc_callback(callback: WindowProcCallback) { let mut window_proc_callbacks = WINDOW_PROC_CALLBACKS.lock().unwrap(); - window_proc_callbacks.push(callback); } pub fn update_keyboard() { let mut queued_states = QUEUED_STATES.lock().unwrap(); - while queued_states.is_empty() == false { + while !queued_states.is_empty() { let state = queued_states.pop_front().unwrap(); - let keyboard_callbacks = KEYBOAD_CALLBACKS.lock().unwrap().clone(); + let keyboard_callbacks = KEYBOARD_CALLBACKS.lock().unwrap().clone(); for callback in keyboard_callbacks { callback(state); @@ -152,7 +156,7 @@ fn char_for_key_state(key: u32, scan_code: u8, alt_pressed: bool) -> u16 { return 0; } - return char_value; + char_value } unsafe extern "system" fn proc_window( @@ -207,7 +211,7 @@ fn on_keyboard_message( is_up_now: bool, ) { if (key as u8) < KEYS_SIZE { - let mut key_states = KEY_STATES.lock().unwrap(); + let mut key_states = key_states().lock().unwrap(); key_states.insert( key as u8, @@ -224,7 +228,7 @@ fn on_keyboard_message( for _ in 0..repeats { queued_states.push_back(KeyboardCallbackState { key: key as u8, - is_pressed: is_up_now == false, + is_pressed: !is_up_now, character: std::char::from_u32(char_for_key_state(key, scan_code, is_with_alt) as u32) .unwrap(), }); diff --git a/hook/src/lib.rs b/hook/src/lib.rs index 6264d18..cbac9c8 100644 --- a/hook/src/lib.rs +++ b/hook/src/lib.rs @@ -1,4 +1,6 @@ #![recursion_limit = "1024"] +#![allow(unsafe_op_in_unsafe_fn)] + use cpp::cpp; pub use d3drenderer::register_present_callback; use retour::static_detour; @@ -20,7 +22,7 @@ mod keyboard; mod memory; #[macro_use] pub(crate) mod native_handling; -#[allow(warnings)] +#[allow(dead_code, unused_variables)] pub mod natives; mod replay_interface; mod script_patches; @@ -31,7 +33,7 @@ static_detour! { } pub(crate) static mut SCRIPT_CALLBACK: Option = None; -static LABEL: &str = "Loading CryV Multiplayer\0"; +static LABEL: &str = "Loading Phantom Multiplayer\0"; type AddressToEntity = fn(*mut c_void) -> i32; type SwapchainPresent = fn(*mut winapi::shared::dxgi::IDXGISwapChain, u32, u32) -> HRESULT; @@ -89,7 +91,7 @@ fn swapchain_present( let obj = (&(obj as *const SwapchainPresent) as *const *const SwapchainPresent) as *const SwapchainPresent; - return (*obj)(swapchain, sync_interval, flags); + (*obj)(swapchain, sync_interval, flags) } } @@ -203,14 +205,11 @@ fn hook_get_label_text() { GetLabelText.initialize(std::mem::transmute(POINTERS.get_label_text), get_label_text) } { error!("Error initializing GetLabelText hook: {}", error); - return; } if let Err(error) = unsafe { GetLabelText.enable() } { error!("Error enabling GetLabelText hook: {}", error); - - return; } } diff --git a/hook/src/memory.rs b/hook/src/memory.rs index 7fb9c46..1a3c854 100644 --- a/hook/src/memory.rs +++ b/hook/src/memory.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_op_in_unsafe_fn)] + use cpp::cpp; use std::ffi::{c_void, CString}; diff --git a/hook/src/native_handling.rs b/hook/src/native_handling.rs index ff28e6a..321a958 100644 --- a/hook/src/native_handling.rs +++ b/hook/src/native_handling.rs @@ -1,11 +1,13 @@ -use std::{ffi::c_void, sync::Mutex}; +#![allow(unsafe_op_in_unsafe_fn)] + +use std::ffi::c_void; +use std::sync::{Mutex, OnceLock}; use crate::crossmap::CROSSMAP; use crate::script_patches; use cpp::cpp; use retour::static_detour; use log::error; -use once_cell::sync::OnceCell; use winapi::{ shared::minwindef::LPVOID, um::{ @@ -55,11 +57,13 @@ struct FiberWrapper { pointer: *mut c_void, } +// Safety: Fiber pointers are only accessed cooperatively through SwitchToFiber. +// The fibers are never accessed concurrently from multiple OS threads. unsafe impl Send for FiberWrapper {} -static MAIN_FIBER: OnceCell> = OnceCell::new(); -static SCRIPT_FIBER: OnceCell> = OnceCell::new(); -static mut WAKE_AT: u32 = 0; // TODO: Find better solution for this +static MAIN_FIBER: OnceLock> = OnceLock::new(); +static SCRIPT_FIBER: OnceLock> = OnceLock::new(); +static mut WAKE_AT: u32 = 0; fn handler(hash: u64) -> Option<*mut c_void> { if hash == 0 { @@ -88,19 +92,11 @@ fn handler(hash: u64) -> Option<*mut c_void> { } pub(crate) fn get_native_handler(hash: u64) -> Option<*mut c_void> { - // TODO: Implement native handler caching - - match handler(hash) { - Some(value) => Some(value), - None => None, - } + handler(hash) } pub(crate) fn map_native(in_native: u64) -> Option { - match CROSSMAP.get(&in_native) { - Some(value) => Some(*value), - None => None, - } + CROSSMAP.get(&in_native).copied() } pub(crate) fn hook_get_frame_count() { @@ -111,7 +107,6 @@ pub(crate) fn hook_get_frame_count() { "Could not find translation for native: {}", GET_FRAME_COUNT_NATIVE ); - return; } }; @@ -120,7 +115,6 @@ pub(crate) fn hook_get_frame_count() { Some(value) => value, None => { error!("Could not find native handler for native: {}", native); - return; } }; @@ -129,14 +123,11 @@ pub(crate) fn hook_get_frame_count() { unsafe { GetFrameCount.initialize(std::mem::transmute(address), get_frame_count) } { error!("Error initializing GetFrameCount hook: {}", error); - return; } if let Err(error) = unsafe { GetFrameCount.enable() } { error!("Error enabling GetFrameCount hook: {}", error); - - return; } } @@ -155,7 +146,6 @@ fn on_tick() { let script_fiber = SCRIPT_FIBER.get_or_init(|| { has_initialized = true; - // Create fiber for script function let func: LPFIBER_START_ROUTINE = Some(script_function); Mutex::new(FiberWrapper { @@ -179,7 +169,6 @@ unsafe extern "system" fn script_function(_: LPVOID) { Some(value) => value(), None => { error!("It is required to provide a script callback!"); - return; } } @@ -202,14 +191,12 @@ pub(crate) unsafe fn script_wait(time: u32) { if let Some(value) = main_fiber { let main_fiber_value = *value.lock().unwrap(); - SwitchToFiber(main_fiber_value.pointer); } } fn get_frame_count(context: *mut c_void) -> *mut c_void { on_tick(); - context } @@ -244,7 +231,6 @@ pub(crate) fn invoke_call(native_handler: *mut c_void) -> R { unsafe { *(data as *mut R) } } -// TODO: Implement this in Rust cpp! {{ #include @@ -421,74 +407,6 @@ struct NativeRegistrationNew { } }; - -enum eThreadState { - ThreadStateIdle = 0x0, - ThreadStateRunning = 0x1, - ThreadStateKilled = 0x2, - ThreadState3 = 0x3, - ThreadState4 = 0x4, -}; - -struct scrThreadContext { - int ThreadID; - int ScriptHash; - eThreadState State; - int _IP; - int FrameSP; - int _SPP; - float TimerA; - float TimerB; - int TimerC; - int _mUnk1; - int _mUnk2; - int _f2C; - int _f30; - int _f34; - int _f38; - int _f3C; - int _f40; - int _f44; - int _f48; - int _f4C; - int _f50; - int pad1; - int pad2; - int pad3; - int _set1; - int pad[17]; -}; - -struct scrThread { - void *vTable; - scrThreadContext m_ctx; - void *m_pStack; - void *pad; - void *pad2; - const char *m_pszExitMessage; -}; - -struct ScriptThread : scrThread { - const char Name[64]; - void *m_pScriptHandler; - const char gta_pad2[40]; - const char flag1; - const char m_networkFlag; - bool bool1; - bool bool2; - bool bool3; - bool bool4; - bool bool5; - bool bool6; - bool bool7; - bool bool8; - bool bool9; - bool bool10; - bool bool11; - bool bool12; - const char gta_pad3[10]; -}; - static NativeManagerContext _context; static uint64_t _hash; void(*ScrNativeCallContext::SetVectorResults)(ScrNativeCallContext*) = nullptr; @@ -510,6 +428,7 @@ uint64_t *nativeCall(NativeHandler function) { function(&_context); ScrNativeCallContext::SetVectorResults(&_context); } __except (exceptionAddress = (GetExceptionInformation())->ExceptionRecord->ExceptionAddress, EXCEPTION_EXECUTE_HANDLER) { + // Native call failed at the exception address captured above } } diff --git a/hook/src/replay_interface.rs b/hook/src/replay_interface.rs index 5f6013c..1f45614 100644 --- a/hook/src/replay_interface.rs +++ b/hook/src/replay_interface.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_op_in_unsafe_fn)] + use crate::POINTERS; #[repr(C)] @@ -19,18 +21,6 @@ pub struct CObjectInterface { pub current_objects: i32, } -impl CObjectInterface { - fn _get_object(&self, index: usize) -> *mut CObject { - if index < self.max_objects as usize { - unsafe { - return (*self.object_list).object_handles[index].object; - } - } - - std::ptr::null_mut() - } -} - #[repr(C)] pub struct CObjectList { pub object_handles: [CObjectHandle; 2300], @@ -64,7 +54,6 @@ impl CPedInterface { return (*self.ped_list).ped_handles[index].ped; } } - std::ptr::null_mut() } } @@ -101,7 +90,6 @@ impl CVehicleInterface { return (*self.vehicle_list).vehicle_handles[index].vehicle; } } - std::ptr::null_mut() } } diff --git a/hook/src/script_patches.rs b/hook/src/script_patches.rs index 877c559..2cbd20a 100644 --- a/hook/src/script_patches.rs +++ b/hook/src/script_patches.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_op_in_unsafe_fn)] + use crate::memory; #[repr(C)] @@ -53,7 +55,7 @@ struct ScriptTableItem { impl ScriptTableItem { fn is_loaded(&self) -> bool { - self.header != std::ptr::null_mut() + !self.header.is_null() } } @@ -66,7 +68,7 @@ struct ScriptTable { impl ScriptTable { fn find_script(&self, hash: i32) -> *mut ScriptTableItem { - if self.table_ptr == std::ptr::null_mut() { + if self.table_ptr.is_null() { return std::ptr::null_mut(); } @@ -95,8 +97,8 @@ impl GlobalTable { fn is_initialized(&self) -> bool { unsafe { - self.global_base_ptr != std::ptr::null_mut() - && *self.global_base_ptr != std::ptr::null_mut() + !self.global_base_ptr.is_null() + && !(*self.global_base_ptr).is_null() } } } @@ -119,16 +121,16 @@ pub unsafe fn patch_multiplayer_vehicles() { let script_table = script_table_pointer as *mut ScriptTable; - while global_table.is_initialized() == false { + while !global_table.is_initialized() { std::thread::sleep(std::time::Duration::from_millis(50)); } let script_table_item = (*script_table).find_script(0x39DA738B); - if script_table_item == std::ptr::null_mut() { + if script_table_item.is_null() { return; } - while (*script_table_item).is_loaded() == false { + while !(*script_table_item).is_loaded() { std::thread::sleep(std::time::Duration::from_millis(50)); } @@ -145,7 +147,7 @@ pub unsafe fn patch_multiplayer_vehicles() { size, ); - if address != std::ptr::null_mut() { + if !address.is_null() { let global_index = (*(address.add(17) as *mut i32)) & 0xFFFFFF; (*global_table.address_of(global_index)) = 1; } diff --git a/launcher/Cargo.toml b/launcher/Cargo.toml index 8de934d..3be5099 100644 --- a/launcher/Cargo.toml +++ b/launcher/Cargo.toml @@ -2,11 +2,9 @@ name = "launcher" version = "0.1.0" authors = ["Alexander Serdyuk "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +edition = "2024" [dependencies] -winreg = "0.8.0" +winreg = "0.52" winapi = { version = "0.3", features = ["winuser", "memoryapi", "libloaderapi", "processthreadsapi"] } -sysinfo = "0.17.2" +sysinfo = "0.33" diff --git a/launcher/src/main.rs b/launcher/src/main.rs index e508007..0fa2d40 100644 --- a/launcher/src/main.rs +++ b/launcher/src/main.rs @@ -1,9 +1,8 @@ extern crate winapi; use std::ffi::CString; -use sysinfo::{ProcessExt, SystemExt}; +use sysinfo::System; use winapi::shared::minwindef::DWORD; -use winapi::shared::winerror::ERROR_INVALID_HANDLE; use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA}; use winapi::um::memoryapi::{VirtualAllocEx, WriteProcessMemory}; use winapi::um::processthreadsapi::{CreateRemoteThread, OpenProcess}; @@ -12,92 +11,62 @@ use winreg::enums::HKEY_LOCAL_MACHINE; use winreg::RegKey; fn main() { - // let path = match get_gta_path() { - // Some(path) => path, - // None => { - // println!("Could not find GTA5 path!"); - - // return; - // } - // }; - - let path: String = "D:\\SteamLibrary\\steamapps\\common\\Grand Theft Auto V\\GTAVLauncher.exe".to_owned(); + let path = match get_gta_path() { + Some(path) => path, + None => { + println!("Could not find GTA5 path! Make sure the game is installed via Steam or Rockstar Games Launcher."); + return; + } + }; println!("Grand Theft Auto V Path: {}", path); - let dll_path = std::env::current_exe() - .unwrap() - .parent() - .unwrap() - .join("client.dll") - .to_str() - .unwrap() - .to_string(); + let dll_path = match std::env::current_exe() { + Ok(exe) => match exe.parent() { + Some(dir) => match dir.join("client.dll").to_str() { + Some(s) => s.to_string(), + None => { + println!("Failed to resolve DLL path"); + return; + } + }, + None => { + println!("Failed to resolve executable directory"); + return; + } + }, + Err(e) => { + println!("Failed to get current executable path: {}", e); + return; + } + }; let dll_directory = std::env::current_exe() - .unwrap() - .parent() - .unwrap() - .to_str() - .unwrap() - .to_string(); + .ok() + .and_then(|exe| exe.parent().map(|p| p.to_string_lossy().to_string())) + .unwrap_or_default(); println!("Current dll path: {}", &dll_path); - println!("Current dll directory: {}", &dll_directory); - write_registry_value( + if let Err(e) = write_registry_value( RegKey::predef(HKEY_LOCAL_MACHINE), - r"Software\Phantom".to_owned(), - "InstallDirectory".to_owned(), - dll_directory, - ) - .unwrap(); + r"Software\Phantom", + "InstallDirectory", + &dll_directory, + ) { + println!("Warning: Could not write registry value (try running as admin): {}", e); + } - if let Err(error) = start_process(path, "".to_owned()) { + if let Err(error) = start_process(&path, "") { println!("Error while trying to start GTA5 process: {}", error); - return; } - let mut process_id = 0; - loop { - let system = sysinfo::System::new_all(); - for (pid, process) in system.get_processes() { - if process.name() == "GTA5.exe" { - process_id = *pid; - - break; - } - } - - if process_id != 0 { - break; - } + let process_id = wait_for_process("GTA5.exe"); + println!("Found GTA5 process with PID: {}", process_id); - std::thread::sleep(std::time::Duration::from_millis(50)); - } - - loop { - let window_name = CString::new("Grand Theft Auto V").unwrap(); - let window_name_pointer = window_name.as_ptr(); - - let handle = unsafe { FindWindowA(std::ptr::null_mut(), window_name_pointer) }; - - let mut foreground_window_id: DWORD = 0; - unsafe { - GetWindowThreadProcessId(handle, &mut foreground_window_id as *mut DWORD); - }; - - let is_window_visible = - unsafe { IsWindowVisible(handle) == winapi::shared::minwindef::TRUE }; - - if foreground_window_id as usize == process_id && is_window_visible { - break; - } - - std::thread::sleep(std::time::Duration::from_millis(50)); - } + wait_for_window("Grand Theft Auto V", process_id); println!("Injecting client"); @@ -105,17 +74,25 @@ fn main() { OpenProcess( winapi::um::winnt::PROCESS_ALL_ACCESS, winapi::shared::minwindef::FALSE, - process_id as u32, + process_id, ) }; - inject_dll(process, dll_path); + if process.is_null() { + println!("Failed to open GTA5 process. Try running as administrator."); + return; + } + + if let Err(e) = inject_dll(process, &dll_path) { + println!("Injection failed: {}", e); + return; + } println!("Done"); } -fn inject_dll(process: *mut winapi::ctypes::c_void, dll_path: String) { - let dll_path_string = CString::new(dll_path.clone()).unwrap(); +fn inject_dll(process: *mut winapi::ctypes::c_void, dll_path: &str) -> Result<(), String> { + let dll_path_string = CString::new(dll_path).map_err(|e| format!("Invalid DLL path: {}", e))?; let dll_path_size = dll_path.len() + 1; let memory_allocation = unsafe { @@ -123,31 +100,33 @@ fn inject_dll(process: *mut winapi::ctypes::c_void, dll_path: String) { process, std::ptr::null_mut(), dll_path_size, - winapi::um::winnt::MEM_COMMIT, - winapi::um::winnt::PAGE_EXECUTE_READWRITE, + winapi::um::winnt::MEM_COMMIT | winapi::um::winnt::MEM_RESERVE, + winapi::um::winnt::PAGE_READWRITE, ) }; + if memory_allocation.is_null() { + return Err("Failed to allocate memory in target process".into()); + } + let mut bytes_written: usize = 0; - unsafe { - if WriteProcessMemory( + let write_result = unsafe { + WriteProcessMemory( process, memory_allocation, dll_path_string.as_ptr() as *mut winapi::ctypes::c_void, dll_path_size, - &mut bytes_written as *mut usize, - ) == ERROR_INVALID_HANDLE as i32 - { - println!("Failed to write memory into target process!"); - - return; - } + &mut bytes_written, + ) }; + if write_result == 0 { + return Err("Failed to write memory into target process".into()); + } + let kernel_string = CString::new("kernel32").unwrap(); let load_library_string = CString::new("LoadLibraryA").unwrap(); - let mut return_value: DWORD = 0; let load_library_address = unsafe { GetProcAddress( LoadLibraryA(kernel_string.as_ptr()), @@ -155,7 +134,12 @@ fn inject_dll(process: *mut winapi::ctypes::c_void, dll_path: String) { ) }; - unsafe { + if load_library_address.is_null() { + return Err("Failed to find LoadLibraryA address".into()); + } + + let mut thread_id: DWORD = 0; + let thread = unsafe { CreateRemoteThread( process, std::ptr::null_mut(), @@ -163,85 +147,110 @@ fn inject_dll(process: *mut winapi::ctypes::c_void, dll_path: String) { Some(std::mem::transmute(load_library_address)), memory_allocation, 0, - &mut return_value, + &mut thread_id, ) }; + + if thread.is_null() { + return Err("Failed to create remote thread in target process".into()); + } + + Ok(()) } -fn start_process(path: String, arguments: String) -> std::io::Result<()> { - std::process::Command::new(path).arg(arguments).spawn()?; +fn wait_for_process(name: &str) -> u32 { + let mut system = System::new_all(); + + loop { + system.refresh_processes(); + for (pid, process) in system.processes() { + if process.name().to_string_lossy() == name { + return pid.as_u32(); + } + } + + std::thread::sleep(std::time::Duration::from_millis(100)); + } +} + +fn wait_for_window(window_name: &str, process_id: u32) { + let window_cstring = CString::new(window_name).unwrap(); + + loop { + let handle = unsafe { FindWindowA(std::ptr::null_mut(), window_cstring.as_ptr()) }; + + if !handle.is_null() { + let mut window_pid: DWORD = 0; + unsafe { + GetWindowThreadProcessId(handle, &mut window_pid); + }; + + let is_visible = unsafe { IsWindowVisible(handle) == winapi::shared::minwindef::TRUE }; + + if window_pid == process_id && is_visible { + return; + } + } + + std::thread::sleep(std::time::Duration::from_millis(100)); + } +} + +fn start_process(path: &str, arguments: &str) -> std::io::Result<()> { + std::process::Command::new(path).arg(arguments).spawn()?; Ok(()) } -// fn get_gta_path() -> Option { -// // Steam Launcher -// if let Ok(value) = read_registry_value( -// RegKey::predef(HKEY_LOCAL_MACHINE), -// r"SOFTWARE\WOW6432Node\Rockstar Games\GTAV".to_owned(), -// "InstallFolderSteam".to_owned(), -// ) { -// println!("Path: {}", value); -// println!("STEAM"); - -// return Some(value); -// } - -// // Former Social Club Launcher -// if let Ok(value) = read_registry_value( -// RegKey::predef(HKEY_LOCAL_MACHINE), -// r"SOFTWARE\WOW6432Node\Rockstar Games\Grand Theft Auto V".to_owned(), -// "InstallFolder".to_owned(), -// ) { -// println!("Path: {}", value); -// println!("SOCIAL CLUB"); - -// return Some(value); -// } - -// // Hacky workaround for Rockstar Games Launcher -// if let Ok(value) = read_registry_value( -// RegKey::predef(HKEY_LOCAL_MACHINE), -// r"SOFTWARE\WOW6432Node\Rockstar Games\Launcher".to_owned(), -// "InstallFolder".to_owned(), -// ) { -// let path = std::path::Path::new(&value); - -// println!("Path: {}", path.to_str().unwrap()); -// println!("ROCKSTAR"); - -// return Some( -// path.parent() -// .unwrap() -// .join(r"Grand Theft Auto V\GTAVLauncher.exe") -// .into_os_string() -// .into_string() -// .unwrap(), -// ); -// } - -// // TODO: Support Epic Games Launcher -// // TODO: If Steam, start directly through steam instead of launching GTAVLauncher.exe - -// None -// } - -// fn read_registry_value(registry_key: RegKey, key: String, name: String) -> std::io::Result { -// let sub_key = registry_key.open_subkey(key)?; -// let value: String = sub_key.get_value(name)?; - -// Ok(value) -// } +fn get_gta_path() -> Option { + // Steam Launcher + if let Ok(value) = read_registry_value( + RegKey::predef(HKEY_LOCAL_MACHINE), + r"SOFTWARE\WOW6432Node\Rockstar Games\GTAV", + "InstallFolderSteam", + ) { + return Some(value); + } + + // Rockstar Games Launcher (formerly Social Club) + if let Ok(value) = read_registry_value( + RegKey::predef(HKEY_LOCAL_MACHINE), + r"SOFTWARE\WOW6432Node\Rockstar Games\Grand Theft Auto V", + "InstallFolder", + ) { + return Some(value); + } + + // Rockstar Games Launcher fallback + if let Ok(value) = read_registry_value( + RegKey::predef(HKEY_LOCAL_MACHINE), + r"SOFTWARE\WOW6432Node\Rockstar Games\Launcher", + "InstallFolder", + ) { + let path = std::path::Path::new(&value); + + return path + .parent() + .map(|p| p.join(r"Grand Theft Auto V\GTAVLauncher.exe")) + .and_then(|p| p.into_os_string().into_string().ok()); + } + + None +} + +fn read_registry_value(registry_key: RegKey, key: &str, name: &str) -> std::io::Result { + let sub_key = registry_key.open_subkey(key)?; + let value: String = sub_key.get_value(name)?; + Ok(value) +} fn write_registry_value( registry_key: RegKey, - key: String, - name: String, - value: String, + key: &str, + name: &str, + value: &str, ) -> std::io::Result<()> { let (sub_key, _) = registry_key.create_subkey(key)?; - sub_key.set_value(name, &value)?; - Ok(()) } diff --git a/server/Cargo.toml b/server/Cargo.toml index b6aa6e8..449af7e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -2,11 +2,16 @@ name = "server" version = "0.1.0" authors = ["Alexander Serdyuk "] -edition = "2018" +edition = "2024" [dependencies] -chrono = "0.4.19" -fern = "0.6.0" -log = "0.4.14" -once_cell = "1.7.2" +chrono = "0.4" +env_logger = "0.11" +futures-util = "0.3" +glam = { version = "0.29", features = ["serde"] } +log = "0.4" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" shared = { path = "../shared" } +tokio = { version = "1", features = ["full"] } +tokio-tungstenite = "0.24" diff --git a/server/src/main.rs b/server/src/main.rs index ecde8c8..026008f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,34 +1,192 @@ -use shared::bevy::{app::ScheduleRunnerPlugin, core::CorePlugin, prelude::*}; +use futures_util::{SinkExt, StreamExt}; +use log::{error, info, warn}; +use shared::{ClientMessage, ServerMessage}; +use std::collections::HashMap; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::{Mutex, broadcast}; +use tokio_tungstenite::tungstenite::Message; +use std::sync::atomic::{AtomicU32, Ordering}; -fn main() { - create_logger().expect("Something went wrong while creating the logger!"); +type PeerMap = Arc>>; - App::build() - .add_plugin(CorePlugin) - .add_plugin(ScheduleRunnerPlugin::default()) - .run(); +struct PlayerState { + player_id: u32, + name: String, } -fn create_logger() -> Result<(), fern::InitError> { - let log_file_path = format!( - "{}/server.log", - std::env::current_dir().unwrap().to_str().unwrap() - ); - - fern::Dispatch::new() - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record.level(), - message - )) - }) - .level(log::LevelFilter::Debug) - .chain(std::io::stdout()) - .chain(fern::log_file(log_file_path)?) - .apply()?; - - Ok(()) +static NEXT_PLAYER_ID: AtomicU32 = AtomicU32::new(1); + +#[tokio::main] +async fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let addr = "0.0.0.0:9770"; + let listener = TcpListener::bind(addr).await.expect("Failed to bind"); + + info!("Phantom server listening on {}", addr); + + let peers: PeerMap = Arc::new(Mutex::new(HashMap::new())); + let (broadcast_tx, _) = broadcast::channel::<(SocketAddr, String)>(256); + + while let Ok((stream, addr)) = listener.accept().await { + let peers = peers.clone(); + let broadcast_tx = broadcast_tx.clone(); + let broadcast_rx = broadcast_tx.subscribe(); + + tokio::spawn(handle_connection(stream, addr, peers, broadcast_tx, broadcast_rx)); + } +} + +async fn handle_connection( + stream: TcpStream, + addr: SocketAddr, + peers: PeerMap, + broadcast_tx: broadcast::Sender<(SocketAddr, String)>, + mut broadcast_rx: broadcast::Receiver<(SocketAddr, String)>, +) { + let ws_stream = match tokio_tungstenite::accept_async(stream).await { + Ok(ws) => ws, + Err(e) => { + error!("WebSocket handshake failed for {}: {}", addr, e); + return; + } + }; + + info!("New WebSocket connection from {}", addr); + + let player_id = NEXT_PLAYER_ID.fetch_add(1, Ordering::Relaxed); + + let (mut ws_sender, mut ws_receiver) = ws_stream.split(); + + // Send welcome message + let welcome = ServerMessage::Welcome { player_id }; + if let Ok(json) = serde_json::to_string(&welcome) { + let _ = ws_sender.send(Message::Text(json.into())).await; + } + + // Handle incoming messages and broadcast forwarding concurrently + let peers_clone = peers.clone(); + let broadcast_tx_clone = broadcast_tx.clone(); + + let receive_task = tokio::spawn(async move { + while let Some(msg) = ws_receiver.next().await { + match msg { + Ok(Message::Text(text)) => { + match serde_json::from_str::(&text) { + Ok(client_msg) => { + handle_client_message( + &client_msg, + addr, + player_id, + &peers_clone, + &broadcast_tx_clone, + ) + .await; + } + Err(e) => { + warn!("Invalid message from {}: {}", addr, e); + } + } + } + Ok(Message::Close(_)) => break, + Err(e) => { + error!("Error receiving from {}: {}", addr, e); + break; + } + _ => {} + } + } + }); + + let send_task = tokio::spawn(async move { + while let Ok((sender_addr, msg)) = broadcast_rx.recv().await { + if sender_addr != addr { + if ws_sender.send(Message::Text(msg.into())).await.is_err() { + break; + } + } + } + }); + + let _ = receive_task.await; + send_task.abort(); + + // Clean up on disconnect + let mut peers_lock = peers.lock().await; + if let Some(player) = peers_lock.remove(&addr) { + info!("Player {} ({}) disconnected", player.name, player.player_id); + let disconnect_msg = ServerMessage::PlayerDisconnected { + player_id: player.player_id, + }; + if let Ok(json) = serde_json::to_string(&disconnect_msg) { + let _ = broadcast_tx.send((addr, json)); + } + } +} + +async fn handle_client_message( + msg: &ClientMessage, + addr: SocketAddr, + player_id: u32, + peers: &PeerMap, + broadcast_tx: &broadcast::Sender<(SocketAddr, String)>, +) { + match msg { + ClientMessage::Connect { name } => { + info!("Player {} connected as '{}'", player_id, name); + peers.lock().await.insert( + addr, + PlayerState { + player_id, + name: name.clone(), + }, + ); + + let msg = ServerMessage::PlayerConnected { + player_id, + name: name.clone(), + }; + if let Ok(json) = serde_json::to_string(&msg) { + let _ = broadcast_tx.send((addr, json)); + } + } + ClientMessage::Disconnect => { + info!("Player {} requested disconnect", player_id); + } + ClientMessage::PlayerUpdate(transform) => { + let msg = ServerMessage::PlayerUpdate { + player_id, + transform: *transform, + }; + if let Ok(json) = serde_json::to_string(&msg) { + let _ = broadcast_tx.send((addr, json)); + } + } + ClientMessage::EntityUpdate { + entity_id, + transform, + model, + } => { + let msg = ServerMessage::EntityUpdate { + entity_id: *entity_id, + transform: *transform, + model: *model, + }; + if let Ok(json) = serde_json::to_string(&msg) { + let _ = broadcast_tx.send((addr, json)); + } + } + ClientMessage::ChatMessage(message) => { + info!("Player {}: {}", player_id, message); + let msg = ServerMessage::ChatMessage { + player_id, + message: message.clone(), + }; + if let Ok(json) = serde_json::to_string(&msg) { + let _ = broadcast_tx.send((addr, json)); + } + } + } } diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 05ccc46..df6dd73 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -2,12 +2,10 @@ name = "shared" version = "0.1.0" authors = ["Alexander Serdyuk "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +edition = "2024" [dependencies] -bevy = { version = "0.5.0", default-features = false } +glam = { version = "0.29", features = ["serde"] } bincode = "1.3" -log = "0.4.14" -serde = "1.0.125" \ No newline at end of file +log = "0.4" +serde = { version = "1.0", features = ["derive"] } diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 505187a..81dafd1 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -1,8 +1,6 @@ -use bevy::prelude::*; +use glam::Vec3; use serde::{Deserialize, Serialize}; -pub use bevy; - #[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)] pub struct EntityTransform { pub position: Vec3, @@ -20,3 +18,24 @@ impl std::fmt::Display for EntityModel { write!(f, "{:#X}", self.model) } } + +/// Messages sent from client to server. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum ClientMessage { + Connect { name: String }, + Disconnect, + PlayerUpdate(EntityTransform), + EntityUpdate { entity_id: u32, transform: EntityTransform, model: EntityModel }, + ChatMessage(String), +} + +/// Messages sent from server to client. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum ServerMessage { + Welcome { player_id: u32 }, + PlayerConnected { player_id: u32, name: String }, + PlayerDisconnected { player_id: u32 }, + PlayerUpdate { player_id: u32, transform: EntityTransform }, + EntityUpdate { entity_id: u32, transform: EntityTransform, model: EntityModel }, + ChatMessage { player_id: u32, message: String }, +}