Files
cstb-next/src-tauri/src/cmds.rs

303 lines
8.2 KiB
Rust
Raw Normal View History

2024-09-20 09:52:13 +08:00
use crate::steam;
use crate::tool::*;
use crate::tool::updater::{check_update, download_update, install_update, UpdateInfo};
use crate::vdf::preset;
2025-03-27 13:32:30 +08:00
use crate::vdf::preset::VideoConfig;
use crate::wrap_err;
use anyhow::Result;
use std::fs::File;
use std::fs;
2025-11-05 02:24:17 +08:00
use std::path::Path;
use std::io::{BufRead, BufReader};
use tauri::path::BaseDirectory;
use tauri::Manager;
// use tauri_plugin_shell::ShellExt;
// pub type Result<T, String = ()> = Result<T, String>;
2024-09-20 09:52:13 +08:00
#[tauri::command]
pub fn greet(name: &str) -> Result<String, String> {
Ok(format!("Hello, {}! You've been greeted from Rust!", name))
2024-09-20 09:52:13 +08:00
}
// 工具
#[tauri::command]
pub fn launch_game(steam_path: &str, launch_option: &str, server: &str) -> Result<String, String> {
println!(
"{}: launching game on server: {}, with launch Option {}",
steam_path, server, launch_option
);
// wrap_err!(steam::launch_game(steam_path, launch_option, server));
// 如果有错误,打印出来
if let Err(e) = steam::launch_game(steam_path, launch_option, server) {
println!("Error: {}", e);
return Err(e.to_string());
}
// steam::launch_game(steam_path, launch_option, server);
2024-09-20 09:52:13 +08:00
Ok(format!(
2024-09-20 09:52:13 +08:00
"Launching game on server: {}, with launch Option {}",
server, launch_option
))
2024-09-20 09:52:13 +08:00
}
#[tauri::command]
pub fn kill_game() -> Result<String, String> {
Ok(common::kill("cs2.exe"))
2024-09-20 09:52:13 +08:00
}
#[tauri::command]
pub fn check_process_running(process_name: &str) -> Result<bool, String> {
Ok(common::check_process_running(process_name))
}
2024-09-20 09:52:13 +08:00
#[tauri::command]
pub fn kill_steam() -> Result<String, String> {
Ok(common::kill("steam.exe"))
2024-09-20 09:52:13 +08:00
}
// Steam
#[tauri::command]
pub fn get_steam_path() -> Result<String, String> {
wrap_err!(steam::path::get_steam_path())
}
#[tauri::command]
pub fn get_cs_path(name: &str, steam_dir: &str) -> Result<String, String> {
wrap_err!(steam::path::get_cs_path(name, steam_dir))
2024-09-20 09:52:13 +08:00
}
#[tauri::command]
pub fn open_path(path: &str) -> Result<(), String> {
wrap_err!(common::open_path(path))
}
#[tauri::command]
pub fn get_powerplan() -> Result<i32, String> {
#[cfg(target_os = "windows")]
let powerplan = powerplan::get_powerplan()?;
#[cfg(not(target_os = "windows"))]
2025-03-27 11:30:03 +08:00
let powerplan = powerplan::PowerPlanMode::Other as i32;
2025-03-24 09:55:21 +08:00
Ok(powerplan)
}
#[tauri::command]
pub fn set_powerplan(plan: i32) -> Result<(), String> {
#[cfg(target_os = "windows")]
powerplan::set_powerplan(plan)?;
Ok(())
}
#[tauri::command]
pub fn get_steam_users(steam_dir: &str) -> Result<Vec<preset::User>, String> {
wrap_err!(preset::get_users(steam_dir))
}
2024-09-20 09:52:13 +08:00
#[tauri::command]
pub fn set_auto_login_user(user: &str) -> Result<String, String> {
2024-09-20 09:52:13 +08:00
#[cfg(target_os = "windows")]
steam::reg::set_auto_login_user(user)?;
2024-09-20 09:52:13 +08:00
Ok(format!("Set auto login user to {}", user))
2024-09-20 09:52:13 +08:00
}
2025-03-27 13:32:30 +08:00
#[tauri::command]
pub fn get_cs2_video_config(steam_dir: &str, steam_id32: u32) -> Result<VideoConfig, String> {
let p = format!(
"{}/userdata/{}/730/local/cfg/cs2_video.txt",
steam_dir, steam_id32
);
let video = preset::get_cs2_video(p.as_str()).map_err(|e| e.to_string())?;
Ok(video)
}
#[tauri::command]
pub fn set_cs2_video_config(
steam_dir: &str,
steam_id32: u32,
video_config: VideoConfig,
) -> Result<(), String> {
let p = format!(
"{}/userdata/{}/730/local/cfg/cs2_video.txt",
steam_dir, steam_id32
);
preset::set_cs2_video(p.as_str(), video_config).map_err(|e| e.to_string())?;
Ok(())
}
2024-09-20 09:52:13 +08:00
#[tauri::command]
pub fn check_path(path: &str) -> Result<bool, String> {
Ok(std::path::Path::new(&path).exists())
2024-09-20 09:52:13 +08:00
}
///// 录像
#[tauri::command]
pub async fn analyze_replay(app: tauri::AppHandle, path: &str) -> Result<String, String> {
// 检测文件是否存在
if !std::path::Path::new(&path).exists() {
return Err("文件不存在".to_string());
}
// 获取应用配置目录
let config_dir = app
.path()
.resolve("metadata", BaseDirectory::AppConfig)
.expect("无法获取配置目录");
// 确保 metadata 文件夹存在
if !config_dir.exists() {
fs::create_dir_all(&config_dir).expect("无法创建 metadata 文件夹");
}
// 提取文件名部分
let file_name = std::path::Path::new(path)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("default_filename");
// 拼接输出文件路径
let output_path = config_dir.join(format!("{}.json", file_name));
// 确保输出文件存在,如果不存在则创建空文件
if !output_path.exists() {
File::create(&output_path).expect("无法创建输出文件");
}
// 调用项目绑定cli程序
let cli_path = app
.path()
.resolve("resources/csda", BaseDirectory::Resource)
.expect("analyzer not found");
println!("cli path: {}", cli_path.display());
let output = std::process::Command::new(cli_path)
.arg("-demo-path")
.arg(path)
.arg("-format")
.arg("json")
.arg("-minify")
.arg("-output")
.arg(output_path.to_str().expect("路径转换失败"))
.output()
.expect("Failed to execute command");
// 获取输出
let output_str = String::from_utf8_lossy(&output.stdout);
// 打印输出
println!("{}", output_str);
// 返回结果
Ok(output_str.to_string())
}
2025-11-05 02:24:17 +08:00
// 帧数测试相关
#[tauri::command]
pub fn get_console_log_path(cs_path: &str) -> Result<String, String> {
// cs_path 是类似 "game\bin\win64" 的路径,需要向上找到 game\csgo\console.log
let path = Path::new(cs_path);
// 向上找到 game 目录
if let Some(game_dir) = path.ancestors().find(|p| {
p.file_name()
.and_then(|n| n.to_str())
.map(|n| n == "game")
.unwrap_or(false)
}) {
let console_log_path = game_dir.join("csgo").join("console.log");
Ok(console_log_path.to_string_lossy().to_string())
} else {
Err("无法找到 game 目录".to_string())
}
}
#[tauri::command]
pub fn read_vprof_report(console_log_path: &str) -> Result<String, String> {
let path = Path::new(console_log_path);
if !path.exists() {
return Err("console.log 文件不存在".to_string());
}
let file = File::open(path).map_err(|e| format!("无法打开文件: {}", e))?;
let reader = BufReader::new(file);
let mut vprof_lines = Vec::new();
let mut in_vprof_section = false;
let mut empty_line_count = 0;
for line_result in reader.lines() {
let line = line_result.map_err(|e| format!("读取行错误: {}", e))?;
// 检测 [VProf] 标记
if line.contains("[VProf]") {
in_vprof_section = true;
empty_line_count = 0;
vprof_lines.push(line.clone());
} else if in_vprof_section {
// 如果在 VProf 部分中
if line.trim().is_empty() {
empty_line_count += 1;
// 如果遇到两个连续的空行,结束 VProf 部分
if empty_line_count >= 2 {
break;
}
vprof_lines.push(line.clone());
} else {
empty_line_count = 0;
vprof_lines.push(line.clone());
}
}
}
if vprof_lines.is_empty() {
return Err("未找到 [VProf] 报告".to_string());
}
Ok(vprof_lines.join("\n"))
}
// 更新相关命令
/// 检查更新
#[tauri::command]
pub async fn check_app_update(
app: tauri::AppHandle,
custom_endpoint: Option<String>,
github_repo: Option<String>,
) -> Result<Option<UpdateInfo>, String> {
let current_version = app.package_info().version.to_string();
wrap_err!(check_update(
custom_endpoint.as_deref(),
github_repo.as_deref(),
&current_version
).await)
}
/// 下载更新
#[tauri::command]
pub async fn download_app_update(
app: tauri::AppHandle,
download_url: String,
) -> Result<String, String> {
let path = wrap_err!(download_update(
&app,
&download_url,
None // 可以添加进度回调
).await)?;
Ok(path.to_string_lossy().to_string())
}
/// 安装更新
#[tauri::command]
pub fn install_app_update(installer_path: String) -> Result<(), String> {
wrap_err!(install_update(&installer_path))
}