diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..81f2f35 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 160 +use_small_heuristics = "Default" \ No newline at end of file diff --git a/src/about_dialog.rs b/src/about_dialog.rs index 69adfd5..859be32 100644 --- a/src/about_dialog.rs +++ b/src/about_dialog.rs @@ -28,11 +28,7 @@ impl GameCheetahEngine { ui.label(fl!(crate::LANGUAGE_LOADER, "about-dialog-description")); ui.add_space(12.0); // ui.separator(); - ui.label(fl!( - crate::LANGUAGE_LOADER, - "about-dialog-created_by", - authors = env!("CARGO_PKG_AUTHORS") - )); + ui.label(fl!(crate::LANGUAGE_LOADER, "about-dialog-created_by", authors = env!("CARGO_PKG_AUTHORS"))); ui.add_space(8.0); // ui.separator(); }); @@ -43,9 +39,7 @@ impl GameCheetahEngine { .show_inside(ui, |ui| { ui.add_space(8.0); // ui.separator(); ui.vertical_centered(|ui| { - let button: egui::Button = - egui::Button::new(fl!(crate::LANGUAGE_LOADER, "about-dialog-ok")) - .min_size(Vec2::new(100.0, 24.0)); + let button: egui::Button = egui::Button::new(fl!(crate::LANGUAGE_LOADER, "about-dialog-ok")).min_size(Vec2::new(100.0, 24.0)); if ui.add(button).clicked() { self.show_about_dialog = false; } diff --git a/src/app.rs b/src/app.rs index a8291a3..591dbc9 100644 --- a/src/app.rs +++ b/src/app.rs @@ -7,9 +7,7 @@ use std::{ time::{Duration, SystemTime}, }; -use crate::{ - GameCheetahEngine, Message, MessageCommand, SearchContext, SearchMode, SearchType, SearchValue, -}; +use crate::{GameCheetahEngine, Message, MessageCommand, SearchContext, SearchMode, SearchType, SearchValue}; impl GameCheetahEngine { pub fn new(_: &eframe::CreationContext<'_>) -> Self { @@ -17,14 +15,10 @@ impl GameCheetahEngine { } fn render_process_window(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) { - if SystemTime::now() - .duration_since(self.last_process_update) - .unwrap() - .as_millis() - > 500 - { + if SystemTime::now().duration_since(self.last_process_update).unwrap().as_millis() > 500 { self.update_process_data(); } + if ctx.input(|i| i.key_down(egui::Key::Escape)) { self.show_process_window = false; return; @@ -33,10 +27,7 @@ impl GameCheetahEngine { ui.horizontal(|ui| { ui.spacing_mut().item_spacing = egui::Vec2::splat(5.0); - let i = ui.add( - egui::TextEdit::singleline(&mut self.process_filter) - .hint_text(fl!(crate::LANGUAGE_LOADER, "filter-processes-hint")), - ); + let i = ui.add(egui::TextEdit::singleline(&mut self.process_filter).hint_text(fl!(crate::LANGUAGE_LOADER, "filter-processes-hint"))); if ui.memory(|m| m.focus().is_none()) { ui.memory_mut(|m| m.request_focus(i.id)); } @@ -47,10 +38,7 @@ impl GameCheetahEngine { self.process_filter.clear(); } - if ui - .button(fl!(crate::LANGUAGE_LOADER, "close-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "close-button")).clicked() { self.show_process_window = false; } }); @@ -176,14 +164,10 @@ impl eframe::App for GameCheetahEngine { if ui.button("x").clicked() { self.pid = 0; - self.freeze_sender - .send(Message::from_addr(MessageCommand::Pid, 0)) - .unwrap_or_default(); + self.freeze_sender.send(Message::from_addr(MessageCommand::Pid, 0)).unwrap_or_default(); self.searches.clear(); - self.searches.push(Box::new(SearchContext::new(fl!( - crate::LANGUAGE_LOADER, - "first-search-label" - )))); + self.searches + .push(Box::new(SearchContext::new(fl!(crate::LANGUAGE_LOADER, "first-search-label")))); self.current_search = 0; self.process_filter.clear(); } @@ -204,10 +188,7 @@ impl eframe::App for GameCheetahEngine { ui.close_menu(); } ui.separator(); - if ui - .button(fl!(crate::LANGUAGE_LOADER, "menu-item-about")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "menu-item-about")).clicked() { self.show_about_dialog = true; ui.close_menu(); } @@ -225,10 +206,7 @@ impl eframe::App for GameCheetahEngine { for i in 0..self.searches.len() { let r = ui - .selectable_label( - self.current_search == i, - self.searches[i].description.clone(), - ) + .selectable_label(self.current_search == i, self.searches[i].description.clone()) .on_hover_text(fl!(crate::LANGUAGE_LOADER, "tab-hover-text")); if r.clicked() { @@ -240,10 +218,7 @@ impl eframe::App for GameCheetahEngine { } } if self.current_search < self.searches.len() - && ui - .button("-") - .on_hover_text(fl!(crate::LANGUAGE_LOADER, "close-tab-hover-text")) - .clicked() + && ui.button("-").on_hover_text(fl!(crate::LANGUAGE_LOADER, "close-tab-hover-text")).clicked() { self.remove_freezes(self.current_search); self.searches.remove(self.current_search); @@ -251,11 +226,7 @@ impl eframe::App for GameCheetahEngine { self.current_search -= 1; } } - if ui - .button("+") - .on_hover_text(fl!(crate::LANGUAGE_LOADER, "open-tab-hover-text")) - .clicked() - { + if ui.button("+").on_hover_text(fl!(crate::LANGUAGE_LOADER, "open-tab-hover-text")).clicked() { self.new_search(); } }); @@ -292,10 +263,7 @@ impl GameCheetahEngine { .interactive(matches!(search_context.searching, SearchMode::None)), ); - if ui - .button(fl!(crate::LANGUAGE_LOADER, "rename-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "rename-button")).clicked() { search_context.rename_mode = false; } }); @@ -331,11 +299,7 @@ impl GameCheetahEngine { SearchType::Short, SearchType::Short.get_short_description_text(), ); - ui.selectable_value( - &mut search_context.search_type, - SearchType::Int, - SearchType::Int.get_short_description_text(), - ); + ui.selectable_value(&mut search_context.search_type, SearchType::Int, SearchType::Int.get_short_description_text()); ui.selectable_value( &mut search_context.search_type, SearchType::Int64, @@ -372,14 +336,7 @@ impl GameCheetahEngine { } if re.lost_focus() && re.ctx.input(|i| i.key_down(egui::Key::Enter)) { - let len = self - .searches - .get(search_index) - .unwrap() - .results - .lock() - .unwrap() - .len(); + let len = self.searches.get(search_index).unwrap().results.lock().unwrap().len(); if len == 0 { self.initial_search(search_index); } else { @@ -389,54 +346,27 @@ impl GameCheetahEngine { ui.memory_mut(|m| m.request_focus(re.id)); } - if self.searches.len() <= 1 - && ui - .button("+") - .on_hover_text(fl!(crate::LANGUAGE_LOADER, "open-tab-hover-text")) - .clicked() - { + if self.searches.len() <= 1 && ui.button("+").on_hover_text(fl!(crate::LANGUAGE_LOADER, "open-tab-hover-text")).clicked() { self.new_search(); } } }); let search_context = self.searches.get(search_index).unwrap(); - if !search_context.search_value_text.is_empty() - && search_context - .search_type - .from_string(&search_context.search_value_text) - .is_err() - { - ui.label( - RichText::new(fl!(crate::LANGUAGE_LOADER, "invalid-number-error")) - .color(Color32::from_rgb(200, 0, 0)), - ); + if !search_context.search_value_text.is_empty() && search_context.search_type.from_string(&search_context.search_value_text).is_err() { + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "invalid-number-error")).color(Color32::from_rgb(200, 0, 0))); } - if !matches!( - self.searches.get(search_index).unwrap().searching, - SearchMode::None - ) { + if !matches!(self.searches.get(search_index).unwrap().searching, SearchMode::None) { self.render_search_bar(ui, search_index); ctx.request_repaint_after(Duration::from_millis(200)); return; } - if self - .searches - .get(search_index) - .unwrap() - .search_value_text - .as_str() - .parse::() - .is_ok() - { + if self.searches.get(search_index).unwrap().search_value_text.as_str().parse::().is_ok() { let len = self.searches.get(search_index).unwrap().search_results; if len <= 0 { - if ui - .button(fl!(crate::LANGUAGE_LOADER, "initial-search-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "initial-search-button")).clicked() { self.initial_search(search_index); return; } @@ -451,33 +381,21 @@ impl GameCheetahEngine { ui.spacing_mut().item_spacing = egui::Vec2::splat(5.0); - if ui - .button(fl!(crate::LANGUAGE_LOADER, "update-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "update-button")).clicked() { self.filter_searches(search_index); return; } - if ui - .button(fl!(crate::LANGUAGE_LOADER, "clear-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "clear-button")).clicked() { search_context.clear_results(&self.freeze_sender); return; } if len >= auto_show_treshold { if self.show_results { - if ui - .button(fl!(crate::LANGUAGE_LOADER, "hide-results-button")) - .clicked() - { + if ui.button(fl!(crate::LANGUAGE_LOADER, "hide-results-button")).clicked() { self.show_results = false; return; } - } else if ui - .button(fl!(crate::LANGUAGE_LOADER, "show-results-button")) - .clicked() - { + } else if ui.button(fl!(crate::LANGUAGE_LOADER, "show-results-button")).clicked() { self.show_results = true; return; } @@ -486,11 +404,7 @@ impl GameCheetahEngine { if len == 1 { ui.label(fl!(crate::LANGUAGE_LOADER, "found-one-result-label")); } else { - ui.label(fl!( - crate::LANGUAGE_LOADER, - "found-results-label", - results = len - )); + ui.label(fl!(crate::LANGUAGE_LOADER, "found-results-label", results = len)); } }); @@ -543,14 +457,8 @@ impl GameCheetahEngine { ui.label(format!("0x{:X}", result.addr)); }); row.col(|ui| { - if let Ok(handle) = - (self.pid as process_memory::Pid).try_into_process_handle() - { - if let Ok(buf) = copy_address( - result.addr, - result.search_type.get_byte_length(), - &handle, - ) { + if let Ok(handle) = (self.pid as process_memory::Pid).try_into_process_handle() { + if let Ok(buf) = copy_address(result.addr, result.search_type.get_byte_length(), &handle) { let val = SearchValue(result.search_type, buf); let mut value_text = val.to_string(); let old_text = value_text.clone(); @@ -559,13 +467,8 @@ impl GameCheetahEngine { let val = result.search_type.from_string(&value_text); match val { Ok(value) => { - handle - .put_address(result.addr, &value.1) - .unwrap_or_default(); - if search_context - .freezed_addresses - .contains(&result.addr) - { + handle.put_address(result.addr, &value.1).unwrap_or_default(); + if search_context.freezed_addresses.contains(&result.addr) { self.freeze_sender .send(Message { msg: MessageCommand::Freeze, @@ -576,15 +479,11 @@ impl GameCheetahEngine { } } Err(err) => { - eprintln!( - "Error converting {:?}: {}", - result.search_type, err - ); + eprintln!("Error converting {:?}: {}", result.search_type, err); self.error_text = fl!( crate::LANGUAGE_LOADER, "conversion-error", - valuetype = - result.search_type.get_short_description_text(), + valuetype = result.search_type.get_short_description_text(), message = err ); } @@ -603,14 +502,8 @@ impl GameCheetahEngine { row.col(|ui| { let mut b = search_context.freezed_addresses.contains(&result.addr); if ui.checkbox(&mut b, "").changed() { - if let Ok(handle) = - (self.pid as process_memory::Pid).try_into_process_handle() - { - if let Ok(buf) = copy_address( - result.addr, - result.search_type.get_byte_length(), - &handle, - ) { + if let Ok(handle) = (self.pid as process_memory::Pid).try_into_process_handle() { + if let Ok(buf) = copy_address(result.addr, result.search_type.get_byte_length(), &handle) { if b { search_context.freezed_addresses.insert(result.addr); self.freeze_sender @@ -623,10 +516,7 @@ impl GameCheetahEngine { } else { search_context.freezed_addresses.remove(&(result.addr)); self.freeze_sender - .send(Message::from_addr( - MessageCommand::Unfreeze, - result.addr, - )) + .send(Message::from_addr(MessageCommand::Unfreeze, result.addr)) .unwrap_or_default(); } } @@ -640,10 +530,7 @@ impl GameCheetahEngine { fn render_search_bar(&mut self, ui: &mut egui::Ui, search_index: usize) { let search_context = self.searches.get_mut(search_index).unwrap(); let current_bytes = search_context.current_bytes.load(Ordering::Acquire); - let progress_bar = egui::widgets::ProgressBar::new( - current_bytes as f32 / search_context.total_bytes as f32, - ) - .show_percentage(); + let progress_bar = egui::widgets::ProgressBar::new(current_bytes as f32 / search_context.total_bytes as f32).show_percentage(); match search_context.searching { SearchMode::None => {} SearchMode::Percent => { diff --git a/src/main.rs b/src/main.rs index e47584b..b75857d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,10 +24,14 @@ fn main() { // Log to stdout (if you run with `RUST_LOG=debug`). tracing_subscriber::fmt::init(); - let native_options = eframe::NativeOptions::default(); + let options = eframe::NativeOptions { + multisampling: 0, + icon_data: Some(eframe::IconData::try_from_png_bytes(&include_bytes!("../build/linux/256x256.png")[..]).unwrap()), + ..Default::default() + }; eframe::run_native( format!("{APP_NAME} {VERSION}").as_str(), - native_options, + options, Box::new(|cc| Box::new(game_cheetah::GameCheetahEngine::new(cc))), ) .unwrap(); diff --git a/src/search_type.rs b/src/search_type.rs index 3c3065b..e3193bc 100644 --- a/src/search_type.rs +++ b/src/search_type.rs @@ -79,10 +79,7 @@ impl SearchType { SearchType::Double => { let parsed = txt.parse::(); match parsed { - Ok(f) => Ok(SearchValue( - SearchType::Double, - f64::to_le_bytes(f).to_vec(), - )), + Ok(f) => Ok(SearchValue(SearchType::Double, f64::to_le_bytes(f).to_vec())), Err(_) => Err(fl!(crate::LANGUAGE_LOADER, "invalid-input-error")), } } diff --git a/src/search_value.rs b/src/search_value.rs index 9ed385a..4f120a3 100644 --- a/src/search_value.rs +++ b/src/search_value.rs @@ -13,9 +13,7 @@ impl Display for SearchValue { SearchType::Int => i32::from_le_bytes(self.1.clone().try_into().unwrap()).to_string(), SearchType::Int64 => i64::from_le_bytes(self.1.clone().try_into().unwrap()).to_string(), SearchType::Float => f32::from_le_bytes(self.1.clone().try_into().unwrap()).to_string(), - SearchType::Double => { - f64::from_le_bytes(self.1.clone().try_into().unwrap()).to_string() - } + SearchType::Double => f64::from_le_bytes(self.1.clone().try_into().unwrap()).to_string(), SearchType::Guess => panic!("invalid search value"), }; write!(f, "{s}") diff --git a/src/state.rs b/src/state.rs index 0ddebab..7e2ce5f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,9 +7,7 @@ use std::{ time::{Duration, SystemTime}, }; -use crate::{ - Message, MessageCommand, SearchContext, SearchMode, SearchResult, SearchType, SearchValue, -}; +use crate::{Message, MessageCommand, SearchContext, SearchMode, SearchResult, SearchType, SearchValue}; use boyer_moore_magiclen::BMByte; use i18n_embed_fl::fl; use proc_maps::get_process_maps; @@ -88,10 +86,7 @@ impl Default for GameCheetahEngine { processes: Vec::new(), last_process_update: SystemTime::now(), current_search: 0, - searches: vec![Box::new(SearchContext::new(fl!( - crate::LANGUAGE_LOADER, - "first-search-label" - )))], + searches: vec![Box::new(SearchContext::new(fl!(crate::LANGUAGE_LOADER, "first-search-label")))], search_threads: ThreadPool::new(16), freeze_sender: tx, show_results: false, @@ -102,20 +97,13 @@ impl Default for GameCheetahEngine { impl GameCheetahEngine { pub fn new_search(&mut self) { - let ctx = SearchContext::new(fl!( - crate::LANGUAGE_LOADER, - "search-label", - search = (1 + self.searches.len()).to_string() - )); + let ctx = SearchContext::new(fl!(crate::LANGUAGE_LOADER, "search-label", search = (1 + self.searches.len()).to_string())); self.current_search = self.searches.len(); self.searches.push(Box::new(ctx)); } pub fn initial_search(&mut self, search_index: usize) { - if !matches!( - self.searches.get_mut(search_index).unwrap().searching, - SearchMode::None - ) { + if !matches!(self.searches.get_mut(search_index).unwrap().searching, SearchMode::None) { return; } self.remove_freezes(search_index); @@ -125,11 +113,7 @@ impl GameCheetahEngine { match get_process_maps(self.pid) { Ok(maps) => { self.searches.get_mut(search_index).unwrap().total_bytes = 0; - self.searches - .get_mut(search_index) - .unwrap() - .current_bytes - .swap(0, Ordering::SeqCst); + self.searches.get_mut(search_index).unwrap().current_bytes.swap(0, Ordering::SeqCst); for map in maps { if cfg!(target_os = "windows") { if let Some(file_name) = map.filename() { @@ -142,11 +126,7 @@ impl GameCheetahEngine { continue; } } else { - if !map.is_write() - || map.is_exec() - || map.filename().is_none() - || map.size() < 1024 * 1024 - { + if !map.is_write() || map.is_exec() || map.filename().is_none() || map.size() < 1024 * 1024 { continue; } if let Some(file_name) = map.filename() { @@ -161,19 +141,11 @@ impl GameCheetahEngine { let max_block = 10 * 1024 * 1024; let current_search = self.searches.get(search_index).unwrap(); - let search_for_value = current_search - .search_type - .from_string(¤t_search.search_value_text) - .unwrap(); + let search_for_value = current_search.search_type.from_string(¤t_search.search_value_text).unwrap(); self.error_text.clear(); while size > max_block + 3 { - self.spawn_first_search_thread( - search_for_value.clone(), - start, - max_block + 3, - search_index, - ); + self.spawn_first_search_thread(search_for_value.clone(), start, max_block + 3, search_index); start += max_block; size -= max_block; @@ -183,8 +155,7 @@ impl GameCheetahEngine { } Err(err) => { eprintln!("error getting process maps for pid {}: {}", self.pid, err); - self.error_text = - format!("error getting process maps for pid {}: {}", self.pid, err); + self.error_text = format!("error getting process maps for pid {}: {}", self.pid, err); } } } @@ -193,10 +164,7 @@ impl GameCheetahEngine { self.remove_freezes(search_index); let search_context = self.searches.get_mut(search_index).unwrap(); search_context.searching = SearchMode::Percent; - let old_results_arc: Arc>> = mem::replace( - &mut search_context.results, - Arc::new(Mutex::new(Vec::new())), - ); + let old_results_arc: Arc>> = mem::replace(&mut search_context.results, Arc::new(Mutex::new(Vec::new()))); let old_results = old_results_arc.lock().unwrap(); search_context.total_bytes = old_results.len(); search_context.current_bytes.swap(0, Ordering::SeqCst); @@ -214,20 +182,12 @@ impl GameCheetahEngine { pub fn remove_freezes(&mut self, search_index: usize) { let search_context = self.searches.get_mut(search_index).unwrap(); - GameCheetahEngine::remove_freezes_from( - &self.freeze_sender, - &mut search_context.freezed_addresses, - ); + GameCheetahEngine::remove_freezes_from(&self.freeze_sender, &mut search_context.freezed_addresses); } - pub fn remove_freezes_from( - freeze_sender: &mpsc::Sender, - freezes: &mut std::collections::HashSet, - ) { + pub fn remove_freezes_from(freeze_sender: &mpsc::Sender, freezes: &mut std::collections::HashSet) { for result in freezes.iter() { - freeze_sender - .send(Message::from_addr(MessageCommand::Unfreeze, *result)) - .unwrap_or_default(); + freeze_sender.send(Message::from_addr(MessageCommand::Unfreeze, *result)).unwrap_or_default(); } freezes.clear(); } @@ -262,13 +222,7 @@ impl GameCheetahEngine { }); } - fn spawn_update_thread( - &mut self, - search_index: usize, - old_results_arc: Arc>>, - from: usize, - to: usize, - ) { + fn spawn_update_thread(&mut self, search_index: usize, old_results_arc: Arc>>, from: usize, to: usize) { if from >= to { return; } @@ -297,21 +251,13 @@ impl GameCheetahEngine { }); } - fn spawn_first_search_thread( - &mut self, - search_value: SearchValue, - start: usize, - size: usize, - search_index: usize, - ) { + fn spawn_first_search_thread(&mut self, search_value: SearchValue, start: usize, size: usize, search_index: usize) { let search_context = self.searches.get(search_index).unwrap(); let pid = self.pid; let current_bytes = search_context.current_bytes.clone(); let results: Arc>> = search_context.results.clone(); self.search_threads.execute(move || { - let handle = (pid as process_memory::Pid) - .try_into_process_handle() - .unwrap(); + let handle = (pid as process_memory::Pid).try_into_process_handle().unwrap(); if let Ok(memory_data) = copy_address(start, size, &handle) { match search_value.0 { SearchType::Guess => { @@ -319,24 +265,21 @@ impl GameCheetahEngine { if let Ok(search_value) = SearchType::Int.from_string(&val) { let search_data = &search_value.1; - let r = - search_memory(&memory_data, search_data, SearchType::Int, start); + let r = search_memory(&memory_data, search_data, SearchType::Int, start); if !r.is_empty() { results.lock().unwrap().extend_from_slice(&r); } } if let Ok(search_value) = SearchType::Float.from_string(&val) { let search_data = &search_value.1; - let r = - search_memory(&memory_data, search_data, SearchType::Float, start); + let r = search_memory(&memory_data, search_data, SearchType::Float, start); if !r.is_empty() { results.lock().unwrap().extend_from_slice(&r); } } if let Ok(search_value) = SearchType::Double.from_string(&val) { let search_data = &search_value.1; - let r = - search_memory(&memory_data, search_data, SearchType::Double, start); + let r = search_memory(&memory_data, search_data, SearchType::Double, start); if !r.is_empty() { results.lock().unwrap().extend_from_slice(&r); } @@ -358,21 +301,14 @@ impl GameCheetahEngine { pub(crate) fn select_process(&mut self, process: &ProcessInfo) { self.pid = process.pid; self.freeze_sender - .send(Message::from_addr( - MessageCommand::Pid, - process.pid as usize, - )) + .send(Message::from_addr(MessageCommand::Pid, process.pid as usize)) .unwrap_or_default(); self.process_name = process.name.clone(); self.show_process_window = false; } } -fn update_results( - old_results: &[SearchResult], - value_text: &str, - handle: &T, -) -> Vec +fn update_results(old_results: &[SearchResult], value_text: &str, handle: &T) -> Vec where T: process_memory::CopyAddress, { @@ -380,9 +316,7 @@ where for result in old_results { match result.search_type.from_string(value_text) { Ok(my_int) => { - if let Ok(buf) = - copy_address(result.addr, result.search_type.get_byte_length(), handle) - { + if let Ok(buf) = copy_address(result.addr, result.search_type.get_byte_length(), handle) { let val = SearchValue(result.search_type, buf); if val.1 == my_int.1 { results.push(*result); @@ -398,12 +332,7 @@ where results } -fn search_memory( - memory_data: &Vec, - search_data: &Vec, - search_type: SearchType, - start: usize, -) -> Vec { +fn search_memory(memory_data: &Vec, search_data: &Vec, search_type: SearchType, start: usize) -> Vec { let mut result = Vec::new(); let search_bytes = BMByte::from(search_data).unwrap();