improvements
This commit is contained in:
+11
-12
@@ -7,6 +7,7 @@ use windows::Win32::UI::Input::KeyboardAndMouse::{
|
|||||||
pub const INTERVAL: Duration = Duration::from_secs(60);
|
pub const INTERVAL: Duration = Duration::from_secs(60);
|
||||||
const VK_NUMPAD4: u8 = 0x64;
|
const VK_NUMPAD4: u8 = 0x64;
|
||||||
const VK_NUMPAD6: u8 = 0x66;
|
const VK_NUMPAD6: u8 = 0x66;
|
||||||
|
const PRESS_KEYS: [u8; 2] = [VK_NUMPAD4, VK_NUMPAD6];
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AntiAfk {
|
pub struct AntiAfk {
|
||||||
@@ -25,30 +26,28 @@ impl Default for AntiAfk {
|
|||||||
|
|
||||||
impl AntiAfk {
|
impl AntiAfk {
|
||||||
pub fn activate(&mut self) {
|
pub fn activate(&mut self) {
|
||||||
if util::is_window_focused(GTA_WINDOW_TITLE)
|
if util::win::is_window_focused(GTA_WINDOW_TITLE)
|
||||||
&& !util::is_key_pressed(VK_NUMPAD4 as i32)
|
&& !util::win::is_any_key_pressed(&PRESS_KEYS)
|
||||||
&& !util::is_key_pressed(VK_NUMPAD6 as i32)
|
|
||||||
{
|
{
|
||||||
send(VK_NUMPAD4);
|
send(&PRESS_KEYS);
|
||||||
send(VK_NUMPAD6);
|
|
||||||
}
|
}
|
||||||
self.interval = Instant::now();
|
self.interval = Instant::now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(vk_code: u8) {
|
pub fn send(vk_codes: &[u8]) {
|
||||||
unsafe {
|
vk_codes.iter().for_each(|vk_code: &u8| unsafe {
|
||||||
keybd_event(
|
keybd_event(
|
||||||
vk_code,
|
*vk_code,
|
||||||
u8::try_from(MapVirtualKeyW(u32::from(vk_code), MAP_VIRTUAL_KEY_TYPE(0))).unwrap(),
|
u8::try_from(MapVirtualKeyW(u32::from(*vk_code), MAP_VIRTUAL_KEY_TYPE(0))).unwrap(),
|
||||||
KEYBD_EVENT_FLAGS(0),
|
KEYBD_EVENT_FLAGS(0),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
keybd_event(
|
keybd_event(
|
||||||
vk_code,
|
*vk_code,
|
||||||
u8::try_from(MapVirtualKeyW(u32::from(vk_code), MAP_VIRTUAL_KEY_TYPE(0))).unwrap(),
|
u8::try_from(MapVirtualKeyW(u32::from(*vk_code), MAP_VIRTUAL_KEY_TYPE(0))).unwrap(),
|
||||||
KEYBD_EVENT_FLAGS(2),
|
KEYBD_EVENT_FLAGS(2),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-34
@@ -9,7 +9,6 @@ use crate::{
|
|||||||
util::{
|
util::{
|
||||||
self,
|
self,
|
||||||
consts::{ENHANCED, GTA_WINDOW_TITLE, LEGACY},
|
consts::{ENHANCED, GTA_WINDOW_TITLE, LEGACY},
|
||||||
elevation,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
@@ -21,8 +20,6 @@ use std::{
|
|||||||
sync::LazyLock,
|
sync::LazyLock,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use sysinfo::System;
|
|
||||||
use windows::Win32::Foundation::HANDLE;
|
|
||||||
|
|
||||||
const THEME: catppuccin_egui::Theme = catppuccin_egui::MOCHA;
|
const THEME: catppuccin_egui::Theme = catppuccin_egui::MOCHA;
|
||||||
const WINDOW_SIZE: [f32; 2] = [240.0, 240.0];
|
const WINDOW_SIZE: [f32; 2] = [240.0, 240.0];
|
||||||
@@ -46,16 +43,21 @@ pub enum Stage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Flags {
|
||||||
|
initialized: bool,
|
||||||
|
elevated: bool,
|
||||||
|
debug: bool,
|
||||||
|
closing: bool,
|
||||||
|
current_frame: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct App {
|
pub struct App {
|
||||||
stage: Stage,
|
stage: Stage,
|
||||||
closing: bool,
|
flags: Flags,
|
||||||
debug: bool,
|
pub sysinfo: sysinfo::System,
|
||||||
initialized: bool,
|
pub game_handle: windows::Win32::Foundation::HANDLE,
|
||||||
elevated: bool,
|
|
||||||
current_frame: bool,
|
|
||||||
pub sysinfo: System,
|
|
||||||
pub game_handle: HANDLE,
|
|
||||||
launch: Launch,
|
launch: Launch,
|
||||||
force_close: ForceClose,
|
force_close: ForceClose,
|
||||||
empty_session: EmptySession,
|
empty_session: EmptySession,
|
||||||
@@ -66,13 +68,9 @@ impl Default for App {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
stage: Stage::default(),
|
stage: Stage::default(),
|
||||||
closing: false,
|
flags: Flags::default(),
|
||||||
initialized: false,
|
sysinfo: sysinfo::System::new_all(),
|
||||||
debug: false,
|
game_handle: windows::Win32::Foundation::HANDLE::default(),
|
||||||
elevated: elevation::is_elevated(),
|
|
||||||
current_frame: false,
|
|
||||||
sysinfo: System::new_all(),
|
|
||||||
game_handle: HANDLE::default(),
|
|
||||||
launch: Launch::default(),
|
launch: Launch::default(),
|
||||||
force_close: ForceClose::default(),
|
force_close: ForceClose::default(),
|
||||||
empty_session: EmptySession::default(),
|
empty_session: EmptySession::default(),
|
||||||
@@ -83,7 +81,7 @@ impl Default for App {
|
|||||||
|
|
||||||
impl eframe::App for App {
|
impl eframe::App for App {
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
if !self.initialized {
|
if !self.flags.initialized {
|
||||||
catppuccin_egui::set_theme(ctx, THEME);
|
catppuccin_egui::set_theme(ctx, THEME);
|
||||||
egui_extras::install_image_loaders(ctx);
|
egui_extras::install_image_loaders(ctx);
|
||||||
if let Ok(config) = fs::read_to_string(CONFIG_PATH.as_path()) {
|
if let Ok(config) = fs::read_to_string(CONFIG_PATH.as_path()) {
|
||||||
@@ -95,7 +93,8 @@ impl eframe::App for App {
|
|||||||
style.spacing.item_spacing = egui::vec2(4.0, 4.0);
|
style.spacing.item_spacing = egui::vec2(4.0, 4.0);
|
||||||
style.interaction.selectable_labels = false;
|
style.interaction.selectable_labels = false;
|
||||||
});
|
});
|
||||||
self.initialized = true;
|
self.flags.elevated = util::win::is_elevated();
|
||||||
|
self.flags.initialized = true;
|
||||||
}
|
}
|
||||||
self.run_timers();
|
self.run_timers();
|
||||||
egui::TopBottomPanel::bottom("bottom_panel")
|
egui::TopBottomPanel::bottom("bottom_panel")
|
||||||
@@ -106,11 +105,11 @@ impl eframe::App for App {
|
|||||||
ui.selectable_value(&mut self.stage, Stage::About, "About");
|
ui.selectable_value(&mut self.stage, Stage::About, "About");
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
let button = ui
|
let button = ui
|
||||||
.add_enabled(!self.elevated, egui::Button::new("Elevate"))
|
.add_enabled(!self.flags.elevated, egui::Button::new("Elevate"))
|
||||||
.on_hover_text("Relaunch ourselves as administrator.")
|
.on_hover_text("Relaunch ourselves as administrator.")
|
||||||
.on_disabled_hover_text("We are already running elevated.");
|
.on_disabled_hover_text("We are already running elevated.");
|
||||||
if button.clicked() {
|
if button.clicked() {
|
||||||
elevation::elevate(&mut self.closing);
|
util::win::elevate(&mut self.flags.closing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -127,12 +126,12 @@ impl eframe::App for App {
|
|||||||
Stage::About => self.show_about(ctx, ui),
|
Stage::About => self.show_about(ctx, ui),
|
||||||
});
|
});
|
||||||
if check_debug_keycombo_pressed(ctx) {
|
if check_debug_keycombo_pressed(ctx) {
|
||||||
self.debug = !self.debug;
|
self.flags.debug = !self.flags.debug;
|
||||||
}
|
}
|
||||||
if check_debug_viewport_close_button_pressed(ctx) {
|
if check_debug_viewport_close_button_pressed(ctx) {
|
||||||
self.debug = false;
|
self.flags.debug = false;
|
||||||
}
|
}
|
||||||
if self.debug {
|
if self.flags.debug {
|
||||||
let main_rect = ctx.input(|i| {
|
let main_rect = ctx.input(|i| {
|
||||||
i.viewport()
|
i.viewport()
|
||||||
.clone()
|
.clone()
|
||||||
@@ -151,7 +150,7 @@ impl eframe::App for App {
|
|||||||
.with_icon(load_icon()),
|
.with_icon(load_icon()),
|
||||||
|ctx, _class| {
|
|ctx, _class| {
|
||||||
if check_debug_keycombo_pressed(ctx) {
|
if check_debug_keycombo_pressed(ctx) {
|
||||||
self.debug = !self.debug;
|
self.flags.debug = !self.flags.debug;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
egui::ScrollArea::both()
|
egui::ScrollArea::both()
|
||||||
@@ -164,7 +163,7 @@ impl eframe::App for App {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
ctx.request_repaint_after(Duration::from_millis(100));
|
ctx.request_repaint_after(Duration::from_millis(100));
|
||||||
if self.closing {
|
if self.flags.closing {
|
||||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,20 +210,20 @@ impl App {
|
|||||||
);
|
);
|
||||||
if force_close_button.clicked() && !self.force_close.prompting {
|
if force_close_button.clicked() && !self.force_close.prompting {
|
||||||
self.force_close.prompting();
|
self.force_close.prompting();
|
||||||
self.current_frame = true;
|
self.flags.current_frame = true;
|
||||||
};
|
};
|
||||||
if self.force_close.prompting
|
if self.force_close.prompting
|
||||||
&& self.force_close.interval.elapsed() <= Duration::from_secs(3)
|
&& self.force_close.interval.elapsed() <= Duration::from_secs(3)
|
||||||
{
|
{
|
||||||
if force_close_button.clicked() && !self.current_frame {
|
if force_close_button.clicked() && !self.flags.current_frame {
|
||||||
features::force_close::activate(&mut self.sysinfo);
|
features::force_close::activate(&mut self.sysinfo);
|
||||||
self.force_close = ForceClose::default();
|
self.force_close = ForceClose::default();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.force_close = ForceClose::default();
|
self.force_close = ForceClose::default();
|
||||||
}
|
}
|
||||||
if self.current_frame {
|
if self.flags.current_frame {
|
||||||
self.current_frame = false;
|
self.flags.current_frame = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +244,7 @@ impl App {
|
|||||||
if self.anti_afk.enabled {
|
if self.anti_afk.enabled {
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
ui.add_enabled_ui(false, |ui| {
|
ui.add_enabled_ui(false, |ui| {
|
||||||
ui.label(if util::is_window_focused(GTA_WINDOW_TITLE) {
|
ui.label(if util::win::is_window_focused(GTA_WINDOW_TITLE) {
|
||||||
"GTA is focused."
|
"GTA is focused."
|
||||||
} else {
|
} else {
|
||||||
"GTA is not focused!"
|
"GTA is not focused!"
|
||||||
@@ -264,7 +263,7 @@ impl App {
|
|||||||
.inner_margin(egui::vec2(4.0, 4.0))
|
.inner_margin(egui::vec2(4.0, 4.0))
|
||||||
.stroke(egui::Stroke::new(1.0, THEME.overlay1))
|
.stroke(egui::Stroke::new(1.0, THEME.overlay1))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let response = ui.add_enabled_ui(self.elevated, |ui| {
|
let response = ui.add_enabled_ui(self.flags.elevated, |ui| {
|
||||||
let label = ui.label("Game's network access");
|
let label = ui.label("Game's network access");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let available_width = label.rect.width();
|
let available_width = label.rect.width();
|
||||||
@@ -382,11 +381,11 @@ fn check_debug_viewport_close_button_pressed(ctx: &egui::Context) -> bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_icon() -> eframe::egui::IconData {
|
fn load_icon() -> egui::IconData {
|
||||||
let icon = include_bytes!("../assets/icon.png");
|
let icon = include_bytes!("../assets/icon.png");
|
||||||
let image = image::load_from_memory(icon).unwrap().into_rgba8();
|
let image = image::load_from_memory(icon).unwrap().into_rgba8();
|
||||||
let (width, height) = image.dimensions();
|
let (width, height) = image.dimensions();
|
||||||
eframe::egui::IconData {
|
egui::IconData {
|
||||||
rgba: image.into_raw(),
|
rgba: image.into_raw(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|||||||
+1
-20
@@ -1,22 +1,3 @@
|
|||||||
pub mod consts;
|
pub mod consts;
|
||||||
pub mod countdown;
|
pub mod countdown;
|
||||||
pub mod elevation;
|
pub mod win;
|
||||||
|
|
||||||
use windows::Win32::UI::{
|
|
||||||
Input::KeyboardAndMouse::GetAsyncKeyState,
|
|
||||||
WindowsAndMessaging::{GetForegroundWindow, GetWindowTextW},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn is_window_focused(target_title: &str) -> bool {
|
|
||||||
unsafe {
|
|
||||||
let hwnd = GetForegroundWindow();
|
|
||||||
let mut buffer: [u16; 512] = [0; 512];
|
|
||||||
let length = GetWindowTextW(hwnd, &mut buffer);
|
|
||||||
let current_title = String::from_utf16_lossy(&buffer[..length as usize]);
|
|
||||||
current_title == target_title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_key_pressed(key: i32) -> bool {
|
|
||||||
unsafe { (GetAsyncKeyState(key) as i32 & 0x8000) != 0 }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,34 @@
|
|||||||
use windows::{
|
use windows::{
|
||||||
Win32::Foundation::{CloseHandle, HANDLE},
|
Win32::{
|
||||||
Win32::Security::{GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation},
|
Foundation::{CloseHandle, HANDLE},
|
||||||
Win32::System::Threading::{GetCurrentProcess, OpenProcessToken},
|
Security::{GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation},
|
||||||
Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_HIDE},
|
System::Threading::{GetCurrentProcess, OpenProcessToken},
|
||||||
|
UI::{
|
||||||
|
Input::KeyboardAndMouse::GetAsyncKeyState,
|
||||||
|
Shell::ShellExecuteW,
|
||||||
|
WindowsAndMessaging::SW_HIDE,
|
||||||
|
WindowsAndMessaging::{GetForegroundWindow, GetWindowTextW},
|
||||||
|
},
|
||||||
|
},
|
||||||
core::{HSTRING, PCWSTR},
|
core::{HSTRING, PCWSTR},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
pub fn is_window_focused(target_title: &str) -> bool {
|
||||||
|
unsafe {
|
||||||
|
let hwnd = GetForegroundWindow();
|
||||||
|
let mut buffer: [u16; 512] = [0; 512];
|
||||||
|
let length = GetWindowTextW(hwnd, &mut buffer);
|
||||||
|
let current_title = String::from_utf16_lossy(&buffer[..length as usize]);
|
||||||
|
current_title == target_title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_any_key_pressed(keys: &[u8]) -> bool {
|
||||||
|
keys.iter()
|
||||||
|
.any(|&key| unsafe { (i32::from(GetAsyncKeyState(i32::from(key))) & 0x8000) != 0 })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn elevate(closing: &mut bool) {
|
pub fn elevate(closing: &mut bool) {
|
||||||
let exe = std::env::current_exe().unwrap();
|
let exe = std::env::current_exe().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
Reference in New Issue
Block a user