6 Commits
Author SHA1 Message Date
futile 0ab7727425 0.2.0 2025-04-07 16:02:45 +01:00
futile c73dc4bd86 some little fixes 2025-04-07 16:02:32 +01:00
futile 68cf28dad8 do so many things 2025-04-07 12:19:06 +01:00
futile c284bad06b change stuff and add stuff 2025-04-05 07:06:41 +01:00
futile 57db451958 move util.rs to util/countdown.rs 2025-03-31 12:43:54 +01:00
futile 186fcde20e add justfile 2025-03-31 12:20:39 +01:00
12 changed files with 600 additions and 227 deletions
Generated
+217 -112
View File
@@ -59,7 +59,7 @@ dependencies = [
"accesskit_consumer",
"hashbrown",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
]
@@ -167,19 +167,21 @@ dependencies = [
[[package]]
name = "arboard"
version = "3.4.1"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4"
checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70"
dependencies = [
"clipboard-win",
"core-graphics",
"image",
"log",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-foundation 0.2.2",
"objc2 0.6.0",
"objc2-app-kit 0.3.0",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-foundation 0.3.0",
"parking_lot",
"windows-sys 0.48.0",
"percent-encoding",
"windows-sys 0.59.0",
"x11rb",
]
@@ -500,9 +502,9 @@ dependencies = [
[[package]]
name = "bytemuck_derive"
version = "1.9.2"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ff22c2722516255d1823ce3cc4bc0b154dbc9364be5c905d6baa6eccbbc8774"
checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
dependencies = [
"proc-macro2",
"quote",
@@ -558,9 +560,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.17"
version = "1.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
dependencies = [
"jobserver",
"libc",
@@ -700,25 +702,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
@@ -828,7 +811,7 @@ dependencies = [
"js-sys",
"log",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"parking_lot",
"percent-encoding",
@@ -900,6 +883,21 @@ dependencies = [
"winit",
]
[[package]]
name = "egui_extras"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624659a2e972a46f4d5f646557906c55f1cd5a0836eddbe610fdf1afba1b4226"
dependencies = [
"ahash",
"egui",
"enum-map",
"image",
"log",
"mime_guess2",
"profiling",
]
[[package]]
name = "egui_glow"
version = "0.31.1"
@@ -918,12 +916,6 @@ dependencies = [
"winit",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "emath"
version = "0.31.1"
@@ -939,6 +931,27 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
[[package]]
name = "enum-map"
version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
"serde",
]
[[package]]
name = "enum-map-derive"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "enumflags2"
version = "0.7.11"
@@ -992,9 +1005,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [
"libc",
"windows-sys 0.59.0",
@@ -1019,9 +1032,9 @@ dependencies = [
[[package]]
name = "event-listener-strategy"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener",
"pin-project-lite",
@@ -1044,9 +1057,9 @@ dependencies = [
[[package]]
name = "flate2"
version = "1.1.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1241,7 +1254,7 @@ dependencies = [
"glutin_wgl_sys",
"libloading",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"once_cell",
"raw-window-handle",
@@ -1332,10 +1345,11 @@ dependencies = [
[[package]]
name = "gta-tools"
version = "0.1.2"
version = "0.2.0"
dependencies = [
"catppuccin-egui",
"eframe",
"egui_extras",
"image",
"open",
"static_vcruntime",
@@ -1428,9 +1442,9 @@ dependencies = [
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
[[package]]
name = "icu_normalizer"
@@ -1452,9 +1466,9 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
[[package]]
name = "icu_properties"
@@ -1473,9 +1487,9 @@ dependencies = [
[[package]]
name = "icu_properties_data"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
[[package]]
name = "icu_provider"
@@ -1550,9 +1564,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.8.0"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown",
@@ -1601,10 +1615,11 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.32"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [
"getrandom 0.3.2",
"libc",
]
@@ -1665,7 +1680,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.9.0",
"libc",
"redox_syscall 0.5.10",
"redox_syscall 0.5.11",
]
[[package]]
@@ -1704,9 +1719,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.26"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "malloc_buf"
@@ -1757,10 +1772,28 @@ dependencies = [
]
[[package]]
name = "miniz_oxide"
version = "0.8.5"
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess2"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54028747dfea8e8bf00d3c2d4e83cf023c1accfd5d436335456e9864940cb85"
dependencies = [
"mime",
"phf",
"phf_shared",
"unicase",
]
[[package]]
name = "miniz_oxide"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
dependencies = [
"adler2",
"simd-adler32",
@@ -1935,6 +1968,18 @@ dependencies = [
"objc2-quartz-core",
]
[[package]]
name = "objc2-app-kit"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb"
dependencies = [
"bitflags 2.9.0",
"objc2 0.6.0",
"objc2-core-graphics",
"objc2-foundation 0.3.0",
]
[[package]]
name = "objc2-cloud-kit"
version = "0.2.2"
@@ -1971,6 +2016,28 @@ dependencies = [
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925"
dependencies = [
"bitflags 2.9.0",
"objc2 0.6.0",
]
[[package]]
name = "objc2-core-graphics"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02"
dependencies = [
"bitflags 2.9.0",
"objc2 0.6.0",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
name = "objc2-core-image"
version = "0.2.2"
@@ -2022,6 +2089,18 @@ checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998"
dependencies = [
"bitflags 2.9.0",
"objc2 0.6.0",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "161a8b87e32610086e1a7a9e9ec39f84459db7b3a0881c1f16ca5a2605581c19"
dependencies = [
"bitflags 2.9.0",
"objc2 0.6.0",
"objc2-core-foundation",
]
[[package]]
@@ -2032,7 +2111,7 @@ checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
]
@@ -2118,9 +2197,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.21.1"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "open"
@@ -2194,7 +2273,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.10",
"redox_syscall 0.5.11",
"smallvec",
"windows-targets 0.52.6",
]
@@ -2217,6 +2296,50 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_macros"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
"syn",
"unicase",
]
[[package]]
name = "phf_shared"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
"unicase",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@@ -2339,9 +2462,9 @@ dependencies = [
[[package]]
name = "quick-xml"
version = "0.37.2"
version = "0.37.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003"
checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369"
dependencies = [
"memchr",
]
@@ -2397,26 +2520,6 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
@@ -2428,9 +2531,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.10"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
dependencies = [
"bitflags 2.9.0",
]
@@ -2462,9 +2565,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.0.3"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96"
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
dependencies = [
"bitflags 2.9.0",
"errno",
@@ -2585,6 +2688,12 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "siphasher"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
version = "0.4.9"
@@ -2605,9 +2714,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.14.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
[[package]]
name = "smithay-client-toolkit"
@@ -2733,15 +2842,14 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.33.1"
version = "0.34.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01"
checksum = "a4b93974b3d3aeaa036504b8eefd4c039dced109171c1ae973f1dc63b2c7e4b2"
dependencies = [
"core-foundation-sys",
"libc",
"memchr",
"ntapi",
"rayon",
"objc2-core-foundation",
"windows 0.57.0",
]
@@ -2754,7 +2862,7 @@ dependencies = [
"fastrand",
"getrandom 0.3.2",
"once_cell",
"rustix 1.0.3",
"rustix 1.0.5",
"windows-sys 0.59.0",
]
@@ -2950,6 +3058,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "unicase"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"
version = "1.0.18"
@@ -3192,7 +3306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
dependencies = [
"proc-macro2",
"quick-xml 0.37.2",
"quick-xml 0.37.4",
"quote",
]
@@ -3303,9 +3417,9 @@ dependencies = [
[[package]]
name = "wgpu-hal"
version = "24.0.2"
version = "24.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4317a17171dc20e6577bf606796794580accae0716a69edbc7388c86a3ec9f23"
checksum = "f112f464674ca69f3533248508ee30cb84c67cf06c25ff6800685f5e0294e259"
dependencies = [
"android_system_properties",
"arrayvec",
@@ -3612,15 +3726,6 @@ dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
@@ -3841,7 +3946,7 @@ dependencies = [
"memmap2",
"ndk",
"objc2 0.5.2",
"objc2-app-kit",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"objc2-ui-kit",
"orbclient",
+7 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "gta-tools"
version = "0.1.2"
version = "0.2.0"
edition = "2024"
[dependencies]
@@ -8,12 +8,16 @@ catppuccin-egui = { version = "5.5.0", default-features = false, features = [
"egui31",
] }
eframe = "0.31.1"
image = { version = "0.25.6", default-features = false }
egui_extras = { version = "0.31.1", features = ["image"] }
image = { version = "0.25.6", default-features = false, features = ["png"] }
open = "5.3.2"
sysinfo = "0.33.1"
sysinfo = "0.34.2"
windows = { version = "0.61.1", features = [
"Win32_UI_Input_KeyboardAndMouse",
"Win32_System_Threading",
"Win32_UI_Shell",
"Win32_UI_WindowsAndMessaging",
"Win32_Security",
] }
winreg = "0.55.0"
+6
View File
@@ -0,0 +1,6 @@
set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"]
install:
cargo build --release
upx .\target\release\gta-tools.exe --best
cp .\target\release\gta-tools.exe ~\.cargo\bin\
+5 -5
View File
@@ -1,4 +1,4 @@
use crate::{features, gui::App, util::Countdown};
use crate::{features, gui::App, util::countdown::Countdown};
use std::time::{Duration, Instant};
use sysinfo::System;
use windows::Win32::{
@@ -6,12 +6,12 @@ use windows::Win32::{
System::Threading::{OpenProcess, PROCESS_SUSPEND_RESUME},
};
pub const INTERVAL: Duration = Duration::from_secs(10);
pub const INTERVAL: Duration = Duration::from_secs(8);
const ENHANCED: &str = "GTA5_Enhanced.exe";
const LEGACY: &str = "GTA5.exe";
pub struct EmptySession {
pub enabled: bool,
pub disabled: bool,
pub interval: Instant,
pub countdown: Countdown,
}
@@ -19,9 +19,9 @@ pub struct EmptySession {
impl Default for EmptySession {
fn default() -> Self {
Self {
enabled: true,
disabled: false,
interval: Instant::now(),
countdown: Countdown::new(features::empty_session::INTERVAL.as_secs() as usize),
countdown: Countdown::new(features::empty_session::INTERVAL.as_secs()),
}
}
}
+10 -3
View File
@@ -1,9 +1,7 @@
use crate::util::consts::{ENHANCED, LEGACY};
use std::time::Instant;
use sysinfo::System;
const ENHANCED: &str = "GTA5_Enhanced.exe";
const LEGACY: &str = "GTA5.exe";
pub struct ForceClose {
pub button_text: String,
pub prompting: bool,
@@ -20,6 +18,14 @@ impl Default for ForceClose {
}
}
impl ForceClose {
pub fn prompting(&mut self) {
self.button_text = "Are you sure?".to_string();
self.prompting = true;
self.interval = Instant::now();
}
}
pub fn activate(sysinfo: &mut System) {
sysinfo.refresh_all();
sysinfo
@@ -29,4 +35,5 @@ pub fn activate(sysinfo: &mut System) {
.for_each(|(_, p)| {
p.kill();
});
sysinfo.refresh_all();
}
+72
View File
@@ -0,0 +1,72 @@
#![allow(clippy::zombie_processes)]
use crate::util::consts::{ENHANCED, LEGACY};
use std::{os::windows::process::CommandExt, path::Path, process::Command};
use sysinfo::System;
const FILTER_NAME: &str = "[GTA Tools] Block all traffic for GTA V";
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
fn get_game_exe_path(sysinfo: &mut System) -> Option<&Path> {
sysinfo.refresh_all();
if let Some((_, process)) = sysinfo
.processes()
.iter()
.find(|(_, p)| p.name() == ENHANCED || p.name() == LEGACY)
{
process.exe()
} else {
None
}
}
pub fn block_all(sysinfo: &mut System) {
let Some(exe_path) = get_game_exe_path(sysinfo) else {
return;
};
let exe_path = exe_path.display().to_string();
Command::new("netsh")
.args([
"advfirewall",
"firewall",
"add",
"rule",
&format!("name={FILTER_NAME}"),
"dir=out",
"action=block",
"protocol=ANY",
&format!("program={exe_path}"),
])
.creation_flags(CREATE_NO_WINDOW)
.spawn()
.unwrap();
Command::new("netsh")
.args([
"advfirewall",
"firewall",
"add",
"rule",
&format!("name={FILTER_NAME}"),
"dir=in",
"action=block",
"protocol=ANY",
&format!("program={exe_path}"),
])
.creation_flags(CREATE_NO_WINDOW)
.spawn()
.unwrap();
}
pub fn unblock_all() {
Command::new("netsh")
.args([
"advfirewall",
"firewall",
"delete",
"rule",
&format!("name={FILTER_NAME}"),
])
.creation_flags(CREATE_NO_WINDOW)
.spawn()
.unwrap();
}
+1
View File
@@ -1,4 +1,5 @@
pub mod anti_afk;
pub mod empty_session;
pub mod force_close;
pub mod game_networking;
pub mod launch;
+229 -101
View File
@@ -1,28 +1,53 @@
use crate::features::{
self,
anti_afk::AntiAfk,
empty_session::EmptySession,
force_close::ForceClose,
launch::{Launch, Platform},
use crate::{
features::{
self,
anti_afk::AntiAfk,
empty_session::EmptySession,
force_close::ForceClose,
launch::{Launch, Platform},
},
util::{
consts::{ENHANCED, LEGACY},
elevation,
},
};
use eframe::egui;
use std::time::{Duration, Instant};
use sysinfo::System;
use windows::Win32::Foundation::HANDLE;
const THEME: catppuccin_egui::Theme = catppuccin_egui::MOCHA;
#[derive(Default, PartialEq, Eq)]
pub enum Stage {
#[default]
Main,
About,
Debug,
}
#[allow(clippy::struct_excessive_bools)]
pub struct App {
pub current_frame: bool,
stage: Stage,
debug: bool,
initialized: bool,
elevated: bool,
current_frame: bool,
pub sysinfo: System,
pub game_handle: HANDLE,
pub launch: Launch,
pub force_close: ForceClose,
pub empty_session: EmptySession,
pub anti_afk: AntiAfk,
launch: Launch,
force_close: ForceClose,
empty_session: EmptySession,
anti_afk: AntiAfk,
}
impl Default for App {
fn default() -> Self {
Self {
stage: Stage::default(),
initialized: false,
debug: false,
elevated: elevation::is_elevated(),
current_frame: false,
sysinfo: System::new_all(),
game_handle: HANDLE::default(),
@@ -36,102 +61,206 @@ impl Default for App {
impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
catppuccin_egui::set_theme(ctx, catppuccin_egui::MOCHA);
if !self.initialized {
catppuccin_egui::set_theme(ctx, THEME);
egui_extras::install_image_loaders(ctx);
self.initialized = true;
}
ctx.request_repaint_after(Duration::from_millis(100));
egui::CentralPanel::default().show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Game");
ui.add(egui::Separator::default().horizontal());
});
ui.horizontal(|ui| {
if ui.button("Launch").clicked() {
features::launch::launch(&self.launch.selected);
};
egui::ComboBox::from_label("")
.selected_text(self.launch.selected.to_string())
.width(125.0)
.show_ui(ui, |ui| {
ui.selectable_value(
&mut self.launch.selected,
Platform::Steam,
Platform::Steam.to_string(),
);
ui.selectable_value(
&mut self.launch.selected,
Platform::Rockstar,
Platform::Rockstar.to_string(),
);
ui.selectable_value(
&mut self.launch.selected,
Platform::Epic,
Platform::Epic.to_string(),
);
});
});
let force_close_button = ui.button(&self.force_close.button_text);
if force_close_button.clicked() && !self.force_close.prompting {
self.force_close.button_text = "Are you sure?".to_string();
self.force_close.prompting = true;
self.force_close.interval = Instant::now();
self.current_frame = true;
};
if self.force_close.prompting
&& self.force_close.interval.elapsed() <= Duration::from_secs(3)
{
if force_close_button.clicked() && !self.current_frame {
features::force_close::activate(&mut self.sysinfo);
self.force_close = ForceClose::default();
ctx.input(|i| {
if i.modifiers.all() && i.key_pressed(egui::Key::D) {
self.debug = !self.debug;
if !self.debug && self.stage == Stage::Debug {
self.stage = Stage::Main;
}
} else {
self.force_close = ForceClose::default();
}
if self.current_frame {
self.current_frame = false;
}
});
self.run_timers();
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Session");
ui.add(egui::Separator::default().horizontal());
});
ui.add_enabled_ui(self.empty_session.enabled, |ui| {
ui.horizontal(|ui| {
if ui.button("Empty current session").clicked() {
self.empty_session.interval = Instant::now();
self.empty_session.enabled = false;
features::empty_session::activate(self);
ui.selectable_value(&mut self.stage, Stage::Main, "Main");
ui.selectable_value(&mut self.stage, Stage::About, "About");
if self.debug {
ui.selectable_value(&mut self.stage, Stage::Debug, "Debug");
}
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
let button = ui
.add_enabled(!self.elevated, egui::Button::new("Elevate"))
.on_hover_text("Relaunch ourselves as administrator.")
.on_disabled_hover_text("We are already running elevated.");
if button.clicked() {
elevation::elevate();
}
if !self.empty_session.enabled {
self.empty_session.countdown.count();
} else {
self.empty_session.countdown.reset();
}
if self.empty_session.interval.elapsed() >= features::empty_session::INTERVAL {
features::empty_session::deactivate(self);
self.empty_session.enabled = true;
}
ui.label(&self.empty_session.countdown.i_string);
});
});
ui.checkbox(&mut self.anti_afk.enabled, "Anti AFK")
.on_hover_text("You should be tabbed in\nwhile this is enabled.");
if self.anti_afk.enabled
&& self.anti_afk.interval.elapsed() >= features::anti_afk::INTERVAL
{
features::anti_afk::activate();
self.anti_afk.interval = Instant::now();
}
ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| {
ui.horizontal(|ui| {
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("with love from ");
ui.hyperlink_to("futile", "http://futile.eu");
});
ui.separator();
ui.label(format!("v{}", env!("CARGO_PKG_VERSION")));
});
// ui.separator();
});
});
egui::CentralPanel::default().show(ctx, |ui| {
egui::ScrollArea::both()
.auto_shrink([false, false])
.show(ui, |ui| match self.stage {
Stage::Main => {
self.header(ui, "Game");
self.show_game(ctx, ui);
self.header(ui, "Session");
self.show_session(ctx, ui);
self.header(ui, "Network");
self.show_network(ctx, ui);
}
Stage::About => {
self.show_about(ctx, ui);
}
Stage::Debug => {
self.show_debug(ctx, ui);
}
});
});
}
}
impl App {
#[allow(clippy::unused_self)]
fn header(&self, ui: &mut egui::Ui, text: &str) {
ui.horizontal(|ui| {
ui.label(text);
ui.add(egui::Separator::default().horizontal());
});
}
fn show_game(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) {
ui.horizontal(|ui| {
if ui.button("Launch").clicked() {
features::launch::launch(&self.launch.selected);
};
egui::ComboBox::from_label("")
.selected_text(self.launch.selected.to_string())
.width(120.0)
.show_ui(ui, |ui| {
ui.selectable_value(
&mut self.launch.selected,
Platform::Steam,
Platform::Steam.to_string(),
);
ui.selectable_value(
&mut self.launch.selected,
Platform::Rockstar,
Platform::Rockstar.to_string(),
);
ui.selectable_value(
&mut self.launch.selected,
Platform::Epic,
Platform::Epic.to_string(),
);
});
});
let force_close_button = ui.button(&self.force_close.button_text);
if force_close_button.clicked() && !self.force_close.prompting {
self.force_close.prompting();
self.current_frame = true;
};
if self.force_close.prompting
&& self.force_close.interval.elapsed() <= Duration::from_secs(3)
{
if force_close_button.clicked() && !self.current_frame {
features::force_close::activate(&mut self.sysinfo);
self.force_close = ForceClose::default();
}
} else {
self.force_close = ForceClose::default();
}
if self.current_frame {
self.current_frame = false;
}
}
fn show_session(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) {
ui.add_enabled_ui(!self.empty_session.disabled, |ui| {
ui.horizontal(|ui| {
if ui.button("Empty current session").clicked() {
self.empty_session.interval = Instant::now();
self.empty_session.disabled = true;
features::empty_session::activate(self);
}
ui.label(&self.empty_session.countdown.i_string);
});
});
ui.checkbox(&mut self.anti_afk.enabled, "Anti AFK")
.on_hover_text("You should be tabbed in\nwhile this is enabled.");
if self.anti_afk.enabled && self.anti_afk.interval.elapsed() >= features::anti_afk::INTERVAL
{
features::anti_afk::activate();
self.anti_afk.interval = Instant::now();
}
}
fn show_network(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) {
egui::Frame::new()
.inner_margin(egui::vec2(4.0, 4.0))
.stroke(egui::Stroke::new(1.0, THEME.overlay1))
.show(ui, |ui| {
let response = ui.add_enabled_ui(self.elevated, |ui| {
ui.label("Game's network access");
ui.horizontal(|ui| {
if ui.button("Block").clicked() {
features::game_networking::block_all(&mut self.sysinfo);
};
if ui.button("Unblock").clicked() {
features::game_networking::unblock_all();
};
});
});
response
.response
.on_disabled_hover_text("This requires administrator.\nUse the Elevate button.")
});
}
#[allow(clippy::unused_self)]
fn show_about(&self, _ctx: &egui::Context, ui: &mut egui::Ui) {
ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| {
ui.horizontal(|ui| {
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("with love from ");
ui.hyperlink_to("futile", "http://futile.eu");
});
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.label(format!(
"v{} {}",
env!("CARGO_PKG_VERSION"),
if cfg!(debug_assertions) { "(dev)" } else { "" }
));
});
});
ui.add(egui::Image::new(egui::include_image!("../assets/icon.png")))
});
}
fn show_debug(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) {
let pid = self
.sysinfo
.processes()
.iter()
.find(|(_, p)| p.name() == ENHANCED || p.name() == LEGACY)
.map_or_else(
|| "no pid found!".to_string(),
|(pid, _)| pid.as_u32().to_string(),
);
if ui.button("refresh sysinfo").clicked() {
self.sysinfo.refresh_all();
}
ui.label(format!("gta pid: {pid}"));
}
fn run_timers(&mut self) {
if self.empty_session.disabled {
self.empty_session.countdown.count();
} else {
self.empty_session.countdown.reset();
}
if self.empty_session.interval.elapsed() >= features::empty_session::INTERVAL {
features::empty_session::deactivate(self);
self.empty_session.disabled = false;
}
}
}
@@ -143,7 +272,6 @@ fn load_icon() -> eframe::egui::IconData {
let rgba = image.into_raw();
(rgba, width, height)
};
eframe::egui::IconData {
rgba: icon_rgba,
width: icon_width,
@@ -156,7 +284,7 @@ pub fn run() {
viewport: egui::ViewportBuilder::default()
.with_resizable(false)
.with_maximize_button(false)
.with_inner_size([250.0, 180.0])
.with_inner_size([256.0, 232.0])
.with_icon(load_icon()),
centered: true,
..Default::default()
+2
View File
@@ -0,0 +1,2 @@
pub const ENHANCED: &str = "GTA5_Enhanced.exe";
pub const LEGACY: &str = "GTA5.exe";
+3 -3
View File
@@ -1,15 +1,15 @@
use std::time::{Duration, Instant};
pub struct Countdown {
pub i: usize,
pub i_original: usize,
pub i: u64,
pub i_original: u64,
pub i_string: String,
pub interval: Instant,
pub first_count: bool,
}
impl Countdown {
pub fn new(i: usize) -> Self {
pub fn new(i: u64) -> Self {
Self {
i,
i_original: i,
+45
View File
@@ -0,0 +1,45 @@
use windows::{
Win32::Foundation::{CloseHandle, HANDLE},
Win32::Security::{GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation},
Win32::System::Threading::{GetCurrentProcess, OpenProcessToken},
Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_HIDE},
core::{HSTRING, PCWSTR},
};
pub fn elevate() {
let exe = std::env::current_exe().unwrap();
unsafe {
ShellExecuteW(
None,
&HSTRING::from("runas"),
&HSTRING::from(exe.as_path()),
PCWSTR::null(),
PCWSTR::null(),
SW_HIDE,
);
}
std::process::exit(0);
}
pub fn is_elevated() -> bool {
unsafe {
let mut token: HANDLE = HANDLE::default();
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token).is_ok() {
let mut elevation = TOKEN_ELEVATION::default();
let size = u32::try_from(std::mem::size_of::<TOKEN_ELEVATION>()).unwrap();
let mut ret_size = size;
let result = GetTokenInformation(
token,
TokenElevation,
Some((&raw mut elevation).cast()),
size,
&mut ret_size,
);
CloseHandle(token).unwrap();
if result.is_ok() && elevation.TokenIsElevated != 0 {
return true;
}
}
false
}
}
+3
View File
@@ -0,0 +1,3 @@
pub mod consts;
pub mod countdown;
pub mod elevation;