25 Commits
Author SHA1 Message Date
futile aeb99992bb 0.10.0 2025-11-07 12:26:12 +00:00
futile 8ab6e14560 show git commit hash as monospace 2025-11-07 11:59:57 +00:00
futile b9ebdfdb5c update force close game button width to fit new font 2025-11-07 11:56:26 +00:00
futile 2804812691 replace Ubuntu fonts with Inter 2025-11-07 11:51:38 +00:00
futile 606fb7e191 update readme 2025-11-07 11:37:13 +00:00
futile e2a779b7f5 redo links in about stage a bit 2025-11-07 11:35:56 +00:00
futile a8b04bb72b move colour constants from gui::colours to util::consts::colours 2025-11-07 00:34:42 +00:00
futile c34cf187d5 ensure persistent_state is easier and more infallible to add fields to 2025-11-06 23:55:04 +00:00
futile f07421e75a use newer syntax for cargo instructions in build.rs 2025-11-06 08:53:09 +00:00
futile 8b4a455dc1 make empty_session::activate simply return a bool 2025-11-06 08:45:50 +00:00
futile a1300f8d76 lowkey improve logging 2025-11-06 08:41:53 +00:00
futile 9e623219a5 shorten some paths in main.rs 2025-11-06 05:07:49 +00:00
futile 09e19b6e16 remove hardly useful "windows compilation only" warning 2025-11-06 05:06:57 +00:00
futile 4498c45965 apply clippy suggestion 2025-11-06 04:20:40 +00:00
futile af8a5b1746 persist anti afk toggle 2025-11-06 04:17:03 +00:00
futile 560d9659f4 make git hash embedding more reliable 2025-11-06 03:06:25 +00:00
futile bf086d0442 amend comment 2025-11-06 02:38:13 +00:00
futile a6ea8ad8e2 ignore return of NtResumeProcess in empty_session::deactivate to reduce crashing 2025-11-06 02:37:26 +00:00
futile 4c00d1846b add git commit hash when hovering version info 2025-11-05 00:33:17 +00:00
futile e5e335f4f3 apply clippy suggestion 2025-11-05 00:10:39 +00:00
futile 3ab5987b67 use more unwraps instead of let _ = 2025-11-05 00:08:53 +00:00
futile 2030796337 add description to Cargo.toml after making sure tauri-winres doesn't use it 2025-11-04 23:08:59 +00:00
futile 2edb4f492a get rid of justfile it sucks 2025-11-04 23:08:31 +00:00
futile 114292d912 use tauri-winres instead of winresource & specify some more fields in the windows resource in build.rs 2025-11-04 22:56:03 +00:00
futile 8adc1f49ad add license and author information to Cargo.toml 2025-11-04 20:15:09 +00:00
24 changed files with 303 additions and 233 deletions
Generated
+122 -123
View File
@@ -63,21 +63,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "arboard"
version = "3.6.1"
@@ -261,18 +246,6 @@ dependencies = [
"libc",
]
[[package]]
name = "chrono"
version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"windows-link 0.1.3",
]
[[package]]
name = "clipboard-win"
version = "5.4.1"
@@ -563,6 +536,20 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "embed-resource"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e"
dependencies = [
"cc",
"memchr",
"rustc_version",
"toml",
"vswhom",
"winreg",
]
[[package]]
name = "enum-map"
version = "2.7.3"
@@ -825,21 +812,22 @@ dependencies = [
[[package]]
name = "gta-tools"
version = "0.9.0"
version = "0.10.0"
dependencies = [
"catppuccin-egui",
"chrono",
"eframe",
"egui_extras",
"humantime",
"image",
"log",
"open",
"serde",
"serde_json",
"static_vcruntime",
"strum",
"tauri-winres",
"windows",
"winreg",
"winresource",
]
[[package]]
@@ -854,9 +842,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.5"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "heck"
@@ -871,28 +859,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "iana-time-zone"
version = "0.1.63"
name = "humantime"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core 0.61.2",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
[[package]]
name = "icu_collections"
@@ -1023,9 +993,9 @@ checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285"
[[package]]
name = "indexmap"
version = "2.11.0"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
dependencies = [
"equivalent",
"hashbrown",
@@ -1837,6 +1807,15 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.38.44"
@@ -1897,19 +1876,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.219"
name = "semver"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
@@ -1930,11 +1925,11 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.9"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392"
dependencies = [
"serde",
"serde_core",
]
[[package]]
@@ -2110,6 +2105,16 @@ dependencies = [
"syn",
]
[[package]]
name = "tauri-winres"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074"
dependencies = [
"embed-resource",
"toml",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -2182,14 +2187,17 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.23"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
dependencies = [
"serde",
"indexmap",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_edit",
"toml_datetime 0.7.3",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
@@ -2197,8 +2205,14 @@ name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
[[package]]
name = "toml_datetime"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533"
dependencies = [
"serde",
"serde_core",
]
[[package]]
@@ -2208,18 +2222,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"toml_datetime 0.6.11",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
name = "toml_parser"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
[[package]]
name = "tracing"
@@ -2301,6 +2321,26 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "vswhom"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b"
dependencies = [
"libc",
"vswhom-sys",
]
[[package]]
name = "vswhom-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "walkdir"
version = "2.5.0"
@@ -2568,7 +2608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9579d0e6970fd5250aa29aba5994052385ff55cf7b28a059e484bb79ea842e42"
dependencies = [
"windows-collections",
"windows-core 0.62.0",
"windows-core",
"windows-future",
"windows-link 0.2.0",
"windows-numerics",
@@ -2580,20 +2620,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a90dd7a7b86859ec4cdf864658b311545ef19dbcf17a672b52ab7cefe80c336f"
dependencies = [
"windows-core 0.62.0",
]
[[package]]
name = "windows-core"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.1.3",
"windows-result 0.3.4",
"windows-strings 0.4.2",
"windows-core",
]
[[package]]
@@ -2605,8 +2632,8 @@ dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.2.0",
"windows-result 0.4.0",
"windows-strings 0.5.0",
"windows-result",
"windows-strings",
]
[[package]]
@@ -2615,7 +2642,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2194dee901458cb79e1148a4e9aac2b164cc95fa431891e7b296ff0b2f1d8a6"
dependencies = [
"windows-core 0.62.0",
"windows-core",
"windows-link 0.2.0",
"windows-threading",
]
@@ -2660,19 +2687,10 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8"
dependencies = [
"windows-core 0.62.0",
"windows-core",
"windows-link 0.2.0",
]
[[package]]
name = "windows-result"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-result"
version = "0.4.0"
@@ -2682,15 +2700,6 @@ dependencies = [
"windows-link 0.2.0",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.5.0"
@@ -2990,16 +2999,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "winresource"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edcacf11b6f48dd21b9ba002f991bdd5de29b2da8cc2800412f4b80f677e4957"
dependencies = [
"toml",
"version_check",
]
[[package]]
name = "wit-bindgen"
version = "0.45.0"
+7 -3
View File
@@ -1,13 +1,15 @@
[package]
name = "gta-tools"
version = "0.9.0"
version = "0.10.0"
edition = "2024"
license = "Apache-2.0"
authors = ["futile <git@futile.eu>"]
description = "A toolset of convenient things for GTA V Online."
[dependencies]
catppuccin-egui = { version = "5.6.0", default-features = false, features = [
"egui32",
] }
chrono = { version = "0.4.41", default-features = false, features = ["clock"] }
eframe = { version = "0.32.2", default-features = false, features = [
"glow",
"default_fonts",
@@ -16,7 +18,9 @@ egui_extras = { version = "0.32.2", default-features = false, features = [
"image",
"svg",
] }
humantime = "2.3.0"
image = { version = "0.25.8", default-features = false, features = ["png"] }
log = "0.4.28"
open = "5.3.2"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.143"
@@ -35,4 +39,4 @@ winreg = "0.55.0"
[build-dependencies]
static_vcruntime = "2.0.0"
winresource = "0.1.23"
tauri-winres = "0.3.3"
+1 -1
View File
@@ -19,7 +19,7 @@ You will need the Rust toolchain, which can be obtained [here](https://rustup.rs
Every feature of GTA Tools is Legacy/Enhanced-agnostic. Some functionality of GTA Tools requires administrator access. If necessary, GTA Tools can either be started as admin manually, or, the user can simply use the <kbd>Elevate</kbd> button to relaunch GTA Tools as admin.
It is recommended to always use an up-to-date version of GTA Tools from [releases](https://github.com/elituf/gta-tools/releases). You can also easily access the current latest release by going to the <kbd>About</kbd> page of GTA Tools and clicking the <kbd>↓</kbd> button near the version number.
It is recommended to always use an up-to-date version of GTA Tools from [releases](https://github.com/elituf/gta-tools/releases). You can also easily access this repository by going to the <kbd>About</kbd> page of GTA Tools and clicking the GitHub button beside the version number.
#### Game
Binary file not shown.
Binary file not shown.
Binary file not shown.
+17 -1
View File
@@ -1,7 +1,23 @@
fn main() {
static_vcruntime::metabuild();
winresource::WindowsResource::new()
tauri_winres::WindowsResource::new()
.set("FileDescription", "GTA Tools")
.set("ProductName", "GTA Tools")
.set("LegalCopyright", "futile <git@futile.eu>")
.set_language(0x0009)
.set_icon("assets/icon.ico")
.compile()
.unwrap();
embed_latest_git_hash();
}
fn embed_latest_git_hash() {
let git_rev_parse = std::process::Command::new("git")
.args(["rev-parse", "--short=8", "HEAD"])
.output()
.unwrap();
let git_hash = String::from_utf8(git_rev_parse.stdout).unwrap();
println!("cargo::rustc-env=LATEST_GIT_COMMIT_HASH={git_hash}");
println!("cargo::rerun-if-changed=.git/refs/heads/main");
println!("cargo::rerun-if-changed=.git/HEAD");
}
-15
View File
@@ -1,15 +0,0 @@
set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"]
install:
cargo build --release
cp .\target\release\gta-tools.exe ~\.cargo\bin
cp .\target\release\gta-tools.exe ~\Documents
lint:
cargo clippy -- -W clippy::pedantic -W clippy::nursery -A clippy::cast_sign_loss -A clippy::cast_possible_truncation -A clippy::cast_possible_wrap
lint-full:
cargo clippy -- -W clippy::pedantic -W clippy::nursery -W clippy::unwrap_used
lint-unwraps:
cargo clippy -- -W clippy::unwrap_used
+8 -10
View File
@@ -1,12 +1,11 @@
use crate::util::{
consts::game::{EXE_ENHANCED, EXE_LEGACY},
countdown::Countdown,
log,
system_info::SystemInfo,
};
use std::time::{Duration, Instant};
use windows::Win32::{
Foundation::{CloseHandle, HANDLE, NTSTATUS},
Foundation::{HANDLE, NTSTATUS},
System::Threading::{OpenProcess, PROCESS_SUSPEND_RESUME},
};
@@ -58,25 +57,24 @@ fn get_gta_pid(system_info: &mut SystemInfo) -> Option<u32> {
.map(|p| p.pid())
}
pub fn activate(game_handle: &mut HANDLE, system_info: &mut SystemInfo) -> Result<(), ()> {
pub fn activate(game_handle: &mut HANDLE, system_info: &mut SystemInfo) -> bool {
let Some(pid) = get_gta_pid(system_info) else {
return Err(());
return false;
};
match unsafe { OpenProcess(PROCESS_SUSPEND_RESUME, false, pid) } {
Ok(handle) => *game_handle = handle,
Err(why) => {
let message = format!("failed to suspend game for empty session:\n{why}");
log::log(log::LogLevel::Error, &message);
return Err(());
log::error!("failed to suspend game for empty session:\n{why}");
return false;
}
}
let _ = unsafe { NtSuspendProcess(*game_handle) };
Ok(())
unsafe { NtSuspendProcess(*game_handle) }.unwrap();
true
}
pub fn deactivate(game_handle: &mut HANDLE) {
if !game_handle.is_invalid() {
// ignoring the return because this function behaves very weirdly
let _ = unsafe { NtResumeProcess(*game_handle) };
let _ = unsafe { CloseHandle(*game_handle) };
}
}
+1 -5
View File
@@ -1,6 +1,5 @@
use crate::util::{
consts::game::{EXE_ENHANCED, EXE_LEGACY},
log,
system_info::SystemInfo,
};
use std::time::{Duration, Instant};
@@ -62,10 +61,7 @@ fn activate(system_info: &mut SystemInfo) {
.filter(|p| p.name() == EXE_ENHANCED || p.name() == EXE_LEGACY)
.for_each(|p| {
if !p.kill() {
log::log(
log::LogLevel::Error,
"failed to force close game, probably due to access denied",
);
log::error!("failed to force close game, probably due to access denied");
}
});
system_info.refresh();
+1 -1
View File
@@ -84,7 +84,7 @@ impl GameNetworking {
(FILTER_NAME_IN, NET_FW_RULE_DIR_IN),
(FILTER_NAME_OUT, NET_FW_RULE_DIR_OUT),
] {
let _ = unsafe { rules.Remove(&BSTR::from(filter.0)) };
unsafe { rules.Remove(&BSTR::from(filter.0)) }.unwrap();
let rule: INetFwRule =
unsafe { CoCreateInstance(&NetFwRule, None, CLSCTX_INPROC_SERVER) }.unwrap();
unsafe { rule.SetName(&BSTR::from(filter.0)) }.unwrap();
+3 -2
View File
@@ -26,7 +26,7 @@ pub fn launch(platform: &Platform, version: &LaunchVersion) {
LaunchVersion::Enhanced => "steam://run/3240220",
LaunchVersion::Legacy => "steam://run/271590",
};
let _ = open::that_detached(steam_url);
open::that_detached(steam_url).unwrap();
}
Platform::Rockstar => {
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
@@ -44,6 +44,7 @@ pub fn launch(platform: &Platform, version: &LaunchVersion) {
};
let mut play_gtav_path = PathBuf::from(install_folder);
play_gtav_path.push("PlayGTAV.exe");
// ignoring the return because if it errors that means GTA isn't installed via Rockstar
let _ = Command::new(play_gtav_path).spawn();
}
Platform::Epic => {
@@ -55,7 +56,7 @@ pub fn launch(platform: &Platform, version: &LaunchVersion) {
"com.epicgames.launcher://apps/9d2d0eb64d5c44529cece33fe2a46482?action=launch&silent=true"
}
};
let _ = open::that_detached(epic_url);
open::that_detached(epic_url).unwrap();
}
}
}
+1 -2
View File
@@ -1,5 +1,4 @@
mod app;
mod colours;
pub mod app;
mod debug;
pub mod run;
pub mod settings;
+17 -17
View File
@@ -1,8 +1,11 @@
use crate::{
features,
gui::{colours, settings::Settings, tools, ui_ext::UiExt},
gui::{settings::Settings, tools, ui_ext::UiExt},
util::{
consts::game::WINDOW_TITLE, persistent_state::PersistentState, system_info::SystemInfo, win,
consts::{colours, game::WINDOW_TITLE},
persistent_state::PersistentState,
system_info::SystemInfo,
win,
},
};
use eframe::egui;
@@ -106,7 +109,7 @@ impl App {
});
});
let force_close_button = ui.add_sized(
[104.0, 0.0],
[108.0, 0.0],
egui::Button::new(&self.force_close.button_text),
);
self.force_close
@@ -122,7 +125,6 @@ impl App {
&mut self.game_handle,
&mut self.system_info,
)
.is_ok()
{
self.empty_session.interval = Instant::now();
self.empty_session.disabled = true;
@@ -226,27 +228,24 @@ impl App {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("with ");
ui.scope(|ui| {
ui.style_mut().visuals.hyperlink_color = colours::RED;
ui.hyperlink_to("", "https://github.com/elituf/gta-tools");
ui.style_mut().visuals.override_text_color = Some(colours::RED);
ui.label("");
});
ui.label(" from ");
ui.hyperlink_to("futile", "https://futile.eu");
});
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.style_mut().spacing.button_padding = egui::Vec2::new(4.0, 0.0);
if ui.button("").on_hover_text("View source code").clicked() {
open::that("https://github.com/elituf/gta-tools").unwrap();
}
if cfg!(debug_assertions) {
ui.label("(dev)");
}
ui.label(format!("v{}", env!("CARGO_PKG_VERSION")));
ui.scope(|ui| {
ui.style_mut().spacing.button_padding = egui::Vec2::new(3.0, 0.0);
let button = ui
.button("")
.on_hover_text("Go to current latest version.");
if button.clicked() {
let _ =
open::that("https://github.com/elituf/gta-tools/releases/latest");
}
});
ui.label(format!("v{}", env!("CARGO_PKG_VERSION")))
.on_hover_text(
egui::RichText::new(env!("LATEST_GIT_COMMIT_HASH")).monospace(),
);
});
});
ui.add(egui::Image::new(egui::include_image!(
@@ -261,6 +260,7 @@ impl Drop for App {
// save any persistent state to config file
PersistentState {
launcher: self.launch.selected,
anti_afk_enabled: self.anti_afk.enabled,
settings: self.settings.clone(),
}
.set();
-16
View File
@@ -1,16 +0,0 @@
use crate::features::game_networking::BlockedStatus;
use eframe::egui;
pub const RED: egui::Color32 = egui::Color32::from_rgb(255, 96, 96);
pub const YELLOW: egui::Color32 = egui::Color32::from_rgb(255, 255, 96);
pub const GREEN: egui::Color32 = egui::Color32::from_rgb(96, 255, 96);
impl From<BlockedStatus> for egui::Color32 {
fn from(value: BlockedStatus) -> Self {
match value {
BlockedStatus::Blocked => RED,
BlockedStatus::Failed => YELLOW,
BlockedStatus::Unblocked => GREEN,
}
}
}
+14 -6
View File
@@ -14,8 +14,7 @@ fn app_creator(
let mut app = Box::new(App::default());
// load previously selected launch platform & settings from persistent state
if let Some(persistent_state) = PersistentState::get() {
app.launch.selected = persistent_state.launcher;
app.settings = persistent_state.settings;
persistent_state.apply_to(&mut app);
}
// check if we're elevated. if not, and the user wants an elevated launch - relaunch elevated
if !app.flags.elevated && app.settings.start_elevated {
@@ -38,12 +37,21 @@ fn app_creator(
// load any extra fonts that we need
let mut fonts = egui::FontDefinitions::default();
fonts.font_data.insert(
"Ubuntu-Regular".to_owned(),
egui::FontData::from_static(include_bytes!("../../assets/Ubuntu-Regular.ttf")).into(),
"Inter 18pt Light".to_owned(),
egui::FontData::from_static(include_bytes!("../../assets/Inter_18pt-Light.ttf")).into(),
);
fonts
.families
.get_mut(&egui::FontFamily::Proportional)
.unwrap()
.insert(0, "Inter 18pt Light".to_owned());
fonts.font_data.insert(
"Inter 18pt Regular".to_owned(),
egui::FontData::from_static(include_bytes!("../../assets/Inter_18pt-Regular.ttf")).into(),
);
fonts.families.insert(
egui::FontFamily::Name("Ubuntu-Regular".into()),
vec!["Ubuntu-Regular".to_owned()],
egui::FontFamily::Name("Inter 18pt Regular".into()),
vec!["Inter 18pt Regular".to_owned()],
);
cc.egui_ctx.set_fonts(fonts);
// finally return the App
+1 -1
View File
@@ -13,7 +13,7 @@ impl UiExt for egui::Ui {
self.horizontal(|ui| {
ui.label(egui::RichText::new(text).font(egui::FontId::new(
12.5,
egui::FontFamily::Name("Ubuntu-Regular".into()),
egui::FontFamily::Name("Inter 18pt Regular".into()),
)));
ui.add(egui::Separator::default().horizontal());
});
+8 -7
View File
@@ -1,26 +1,27 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[cfg(not(target_os = "windows"))]
compile_error!("This application must be compiled for Windows.");
mod features;
mod gui;
mod util;
fn init_storage() {
if !crate::util::consts::path::APP_STORAGE.exists() {
std::fs::create_dir_all(crate::util::consts::path::APP_STORAGE.as_path()).unwrap();
if !util::consts::path::APP_STORAGE.exists() {
std::fs::create_dir_all(util::consts::path::APP_STORAGE.as_path()).unwrap();
}
}
fn panic_hook(panic_info: &std::panic::PanicHookInfo<'_>) {
let backtrace = std::backtrace::Backtrace::capture();
let message = format!("{panic_info}\nstack backtrace:\n{backtrace}\n");
crate::util::log::log(crate::util::log::LogLevel::Panic, &message);
let mut message = format!("{panic_info}");
if backtrace.status() == std::backtrace::BacktraceStatus::Captured {
message += &format!("\nstack backtrace:\n{backtrace}");
}
log::error!("{message}");
}
fn main() {
init_storage();
util::logging::Logger::init(log::LevelFilter::Info);
std::panic::set_hook(Box::new(panic_hook));
gui::run::run();
}
+1 -1
View File
@@ -1,6 +1,6 @@
pub mod consts;
pub mod countdown;
pub mod log;
pub mod logging;
pub mod persistent_state;
pub mod system_info;
pub mod win;
+19
View File
@@ -13,3 +13,22 @@ pub mod game {
pub const EXE_LEGACY: &str = "GTA5.exe";
pub const WINDOW_TITLE: &str = "Grand Theft Auto V";
}
pub mod colours {
use crate::features::game_networking::BlockedStatus;
use eframe::egui;
pub const RED: egui::Color32 = egui::Color32::from_rgb(255, 96, 96);
pub const YELLOW: egui::Color32 = egui::Color32::from_rgb(255, 255, 96);
pub const GREEN: egui::Color32 = egui::Color32::from_rgb(96, 255, 96);
impl From<BlockedStatus> for egui::Color32 {
fn from(value: BlockedStatus) -> Self {
match value {
BlockedStatus::Blocked => RED,
BlockedStatus::Failed => YELLOW,
BlockedStatus::Unblocked => GREEN,
}
}
}
}
-20
View File
@@ -1,20 +0,0 @@
use crate::util::consts::path;
use std::{fs::File, io::Write};
use strum::Display;
#[derive(Clone, Copy, Display)]
pub enum LogLevel {
Error,
Panic,
}
pub fn log(level: LogLevel, message: &str) {
let mut file = File::options()
.create(true)
.append(true)
.open(path::APP_LOG.as_path())
.unwrap();
let timestamp = chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, false);
let message = format!("[{timestamp}] [{level}]\n{message}\n\n");
file.write_all(message.as_bytes()).unwrap();
}
+64
View File
@@ -0,0 +1,64 @@
use std::{
fs::File,
io::Write,
sync::{LazyLock, Mutex},
time::SystemTime,
};
pub struct Logger {
file: Mutex<File>,
}
static LOGGER: LazyLock<Logger> = LazyLock::new(|| Logger {
file: File::options()
.create(true)
.append(true)
.open(crate::util::consts::path::APP_LOG.as_path())
.unwrap()
.into(),
});
impl log::Log for Logger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= log::Level::Info
}
fn flush(&self) {}
fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
self.log_to_stderr(record);
self.log_to_file(record);
}
}
}
impl Logger {
pub fn init(level: log::LevelFilter) {
log::set_logger(&*LOGGER)
.map(|()| log::set_max_level(level))
.unwrap();
}
fn log_to_file(&self, record: &log::Record) {
let mut file = self.file.lock().unwrap();
write!(
file,
"[{}][{}]\n{}\n\n",
humantime::format_rfc3339_seconds(SystemTime::now()),
record.level(),
record.args()
)
.unwrap();
file.flush().unwrap();
}
fn log_to_stderr(&self, record: &log::Record) {
eprintln!(
"[{}][{}]\n{}",
humantime::format_rfc3339_seconds(SystemTime::now()),
record.level(),
record.args()
)
}
}
+17 -1
View File
@@ -1,4 +1,8 @@
use crate::{features::launch::Platform, gui::settings::Settings, util::consts::path};
use crate::{
features::launch::Platform,
gui::{app, settings::Settings},
util::consts::path,
};
use serde::{Deserialize, Serialize};
use std::{
fs::{self, File},
@@ -8,6 +12,7 @@ use std::{
#[derive(Serialize, Deserialize)]
pub struct PersistentState {
pub launcher: Platform,
pub anti_afk_enabled: bool,
pub settings: Settings,
}
@@ -23,4 +28,15 @@ impl PersistentState {
let json = serde_json::to_string_pretty(&self).unwrap();
config_file.write_all(json.as_bytes()).unwrap();
}
pub fn apply_to(self, app: &mut app::App) {
let Self {
launcher,
anti_afk_enabled,
settings,
} = self;
app.launch.selected = launcher;
app.anti_afk.enabled = anti_afk_enabled;
app.settings = settings;
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ pub struct Process {
}
impl Process {
pub fn pid(&self) -> u32 {
pub const fn pid(&self) -> u32 {
self.pid
}