diff --git a/config.txt b/config.txt index 36ec768..41fe3c1 100644 --- a/config.txt +++ b/config.txt @@ -12,4 +12,6 @@ message_start_time_utc = '12:00' message_stop_time_utc = '23:00' message_timeout_mins = 8 game = 'Bf1' +seeder_name = 'iiTzArcur' +find_player_max_retries = 10 launcher = 'EADesktop' diff --git a/src/actions/backend.rs b/src/actions/backend.rs index e68073a..7c1c5c4 100644 --- a/src/actions/backend.rs +++ b/src/actions/backend.rs @@ -23,3 +23,102 @@ pub fn ping( Err(_) => log::error!("Couln't send update of client to backend"), } } + +pub fn has_player(cfg: &structs::SeederConfig, game_id: &str) -> bool { + if cfg.game == structs::Games::Bf4 { + return bf4_has_player(cfg, game_id); + } + bf1_has_player(cfg, game_id) +} + +pub fn bf1_has_player(cfg: &structs::SeederConfig, game_id: &str) -> bool { + let url = format!( + "https://api.gametools.network/bf1/players/?gameid={}", + game_id + ); + match ureq::get(&url[..]).call() { + Ok(response) => match response.into_json::() { + Ok(server_info) => { + // if valid timestamp + match chrono::NaiveDateTime::from_timestamp_millis( + server_info.update_timestamp * 1000, + ) { + Some(naive_time) => { + let timestamp_time = + chrono::DateTime::::from_utc(naive_time, chrono::Utc) + .time(); + let current = chrono::Utc::now().time(); + let diff = current - timestamp_time; + if diff.num_minutes() > 2 { + return true; + } + + if !cfg.seeder_name.is_empty() + && (server_info.teams[0].players.contains( + &structs::GametoolsServerPlayer { + name: cfg.seeder_name.clone(), + }, + ) || server_info.teams[1].players.contains( + &structs::GametoolsServerPlayer { + name: cfg.seeder_name.clone(), + }, + )) + { + return true; + } + false + } + None => { + log::error!("no timestamp in players?"); + log::info!("reconnecting..."); + true + } + } + } + Err(e) => { + log::error!("Failed to get info about server to join: {}", e); + log::info!("reconnecting..."); + true + } + }, + Err(e) => { + log::error!("Failed to connect to gametools: {}", e); + log::info!("reconnecting..."); + true + } + } +} + +pub fn bf4_has_player(cfg: &structs::SeederConfig, game_id: &str) -> bool { + let url = format!( + "https://api.gametools.network/bf4/detailedserver/?gameid={}&lang=en-us®ion=all&platform=pc&service=undefined&", + game_id + ); + match ureq::get(&url[..]).call() { + Ok(response) => match response.into_json::() { + Ok(server_info) => { + if !cfg.seeder_name.is_empty() + && !server_info + .players + .unwrap() + .contains(&structs::GametoolsServerPlayer { + name: cfg.seeder_name.clone(), + }) + { + return true; + } + false + } + Err(e) => { + log::error!("Failed to get info about server to join: {}", e); + log::info!("reconnecting..."); + true + } + }, + Err(e) => { + log::error!("Failed to connect to gametools: {}", e); + log::info!("reconnecting..."); + true + } + } +} diff --git a/src/actions/game.rs b/src/actions/game.rs index 17fc709..fa0f565 100644 --- a/src/actions/game.rs +++ b/src/actions/game.rs @@ -190,7 +190,7 @@ pub fn launch( ) { if game_running.load(atomic::Ordering::Relaxed) == 1 { // if it tried to launch but failed twice - if retry_launch.load(atomic::Ordering::Relaxed) == 10 { + if retry_launch.load(atomic::Ordering::Relaxed) >= 10 { launchers::restart_launcher(cfg); // make retries 0 retry_launch.store(0, atomic::Ordering::Relaxed); diff --git a/src/ea_desktop_test.rs b/src/ea_desktop_test.rs index 2d0ddfc..720bda6 100644 --- a/src/ea_desktop_test.rs +++ b/src/ea_desktop_test.rs @@ -36,6 +36,8 @@ fn main() { message_stop_time_utc: "23:00".into(), message_timeout_mins: 8, game: structs::Games::from("bf1"), + seeder_name: "".into(), + find_player_max_retries: 15, launcher: structs::Launchers::from("ea_desktop"), }; cfg.game_location = actions::game::find_game(&cfg); diff --git a/src/functions/seed_server.rs b/src/functions/seed_server.rs index 7210823..688c08b 100644 --- a/src/functions/seed_server.rs +++ b/src/functions/seed_server.rs @@ -95,7 +95,7 @@ fn on_command_changed( } } -fn on_retry( +fn retry_check( cfg: &structs::SeederConfig, kp_seeder: bool, game_info: &structs::GameInfo, @@ -103,16 +103,41 @@ fn on_retry( current_game_id: &str, game_running: &Arc, retry_launch: &Arc, + retry_player_check: &Arc, ) { + // if game isnt running but should: retry if !&game_info.is_running - & ((&seeder_info.action[..] == "joinServer" && seeder_info.rejoin) || kp_seeder) + && ((&seeder_info.action[..] == "joinServer" && seeder_info.rejoin) || kp_seeder) { log::warn!("didn't find game running, starting.."); actions::game::launch(cfg, current_game_id, "soldier", game_running, retry_launch); } + // if game is running, check if in right server if option set //set retries 0 if game_info.is_running { retry_launch.store(0, atomic::Ordering::Relaxed); + + // check if player is in server + if !cfg.seeder_name.is_empty() { + let retries = retry_player_check.load(atomic::Ordering::Relaxed); + if actions::backend::has_player(cfg, current_game_id) { + if retries > 0 { + log::info!("player found"); + } + retry_player_check.store(0, atomic::Ordering::Relaxed) + } else if retries >= cfg.find_player_max_retries { + log::error!( + "player is still not in the server after {} retries", + retries + ); + actions::game::quit(cfg, game_running, retry_launch); + actions::game::launch(cfg, current_game_id, "soldier", game_running, retry_launch); + retry_player_check.store(0, atomic::Ordering::Relaxed); + } else { + retry_player_check.fetch_add(1, atomic::Ordering::Relaxed); + log::info!("player not yet found, try number: {}", retries + 1); + } + } } } @@ -123,6 +148,7 @@ pub fn start( game_running: &Arc, retry_launch: &Arc, message_running: &Arc, + retry_player_check: &Arc, ) { let game_info = actions::game::is_running(cfg); let a_hour = seeder_info.timestamp < chrono::Utc::now().timestamp() - 3600; // 1 hour since last request @@ -159,9 +185,9 @@ pub fn start( // request to old to work with } else if seeder_info.timestamp != old_seeder_info.timestamp && a_hour { log::info!("request older than a hour, not running latest request.") - // retry if game isnt running + // if no new action } else { - on_retry( + retry_check( cfg, kp_seeder, &game_info, @@ -169,6 +195,7 @@ pub fn start( current_game_id, game_running, retry_launch, + retry_player_check, ); } diff --git a/src/main.rs b/src/main.rs index c0c0e7b..273d6b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,7 @@ fn main() { let retry_launch = Arc::new(atomic::AtomicU32::new(0)); let retry_launch_clone_message = Arc::clone(&retry_launch); + let retry_player_check = Arc::new(atomic::AtomicU32::new(0)); // get/set config let cfg: structs::SeederConfig = match confy::load_path("config.txt") { Ok(config) => config, @@ -63,6 +64,8 @@ fn main() { message_stop_time_utc: "23:00".into(), message_timeout_mins: 8, game: structs::Games::from("bf1"), + seeder_name: "".into(), + find_player_max_retries: 15, launcher: structs::Launchers::from("ea_desktop"), }; cfg.game_location = actions::game::find_game(&cfg); @@ -129,6 +132,7 @@ fn main() { &game_running, &retry_launch, &message_running_clone, + &retry_player_check, ); } Err(e) => { diff --git a/src/origin_test.rs b/src/origin_test.rs index 5f9f272..bd1c72b 100644 --- a/src/origin_test.rs +++ b/src/origin_test.rs @@ -36,6 +36,8 @@ fn main() { message_stop_time_utc: "23:00".into(), message_timeout_mins: 8, game: structs::Games::from("bf1"), + seeder_name: "".into(), + find_player_max_retries: 15, launcher: structs::Launchers::from("origin"), }; cfg.game_location = actions::game::find_game(&cfg); diff --git a/src/structs.rs b/src/structs.rs index 84e229c..d5e01b2 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -26,6 +26,8 @@ pub struct SeederConfig { pub message_stop_time_utc: String, pub message_timeout_mins: u32, pub game: Games, + pub seeder_name: String, + pub find_player_max_retries: u32, pub launcher: Launchers, } @@ -69,6 +71,8 @@ impl ::std::default::Default for SeederConfig { message_stop_time_utc: "23:00".into(), message_timeout_mins: 8, game: Games::from("bf1"), + seeder_name: "".into(), + find_player_max_retries: 15, launcher: Launchers::from("ea_desktop"), }; cfg.game_location = actions::game::find_game(&cfg); @@ -88,6 +92,29 @@ pub struct ServerInfo { pub game_id: String, } +#[derive(Deserialize, PartialEq, Eq, Clone, Debug)] +pub struct GametoolsServerPlayer { + pub name: String, +} + +#[derive(Deserialize, PartialEq, Eq, Clone, Debug)] +pub struct GametoolsDetailedServer { + #[serde(rename = "gameId")] + pub game_id: String, + pub players: Option>, +} + +#[derive(Deserialize, PartialEq, Eq, Clone, Debug)] +pub struct GametoolsTeam { + pub players: Vec, +} + +#[derive(Deserialize, PartialEq, Eq, Clone, Debug)] +pub struct GametoolsPlayers { + pub teams: Vec, + pub update_timestamp: i64, +} + #[derive(Clone, Debug)] pub struct EaDesktopNewestFile { pub file_name: String, @@ -121,7 +148,7 @@ impl Launchers { } } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub enum Games { Bf4, Bf1,