[feat] set video config

This commit is contained in:
2025-03-27 15:29:12 +08:00
parent 93cda8dc85
commit 114def0b96
4 changed files with 126 additions and 173 deletions

View File

@@ -1,11 +1,12 @@
pub fn to_json(vdf_data: &str) -> String { pub fn to_json(vdf_data: &str) -> String {
let linebreak = match std::env::consts::OS { let linebreak = match std::env::consts::OS {
"macos" => "\r", "macos" => "\n", //"\r",
"windows" => "\n", "windows" => "\n",
"linux" => "\n", "linux" => "\n",
_ => "\n", _ => "\n",
}; };
// NOTE: 这样会跳过顶层{}
let startpoint = vdf_data.find('{').unwrap_or(0); let startpoint = vdf_data.find('{').unwrap_or(0);
let vdf_data = &vdf_data[startpoint..]; let vdf_data = &vdf_data[startpoint..];
@@ -31,13 +32,15 @@ pub fn to_json(vdf_data: &str) -> String {
json_data.push_str(&line); json_data.push_str(&line);
} }
// let json_str = json_data
json_data = json_data json_data = json_data
.replace(",}", "}") .replace(",}", "}")
.trim_start_matches(": ") .trim_start_matches(": ")
.trim_end_matches(',') .trim_end_matches(',')
.to_string(); .to_string();
// json_data = format!("{{{}}}", json_str);
json_data return json_data;
} }
pub fn to_vdf(json_data: &str) -> String { pub fn to_vdf(json_data: &str) -> String {
@@ -48,33 +51,33 @@ pub fn to_vdf(json_data: &str) -> String {
} }
fn build_vdf(json_value: &serde_json::Value, vdf_data: &mut String, indent_level: usize) { fn build_vdf(json_value: &serde_json::Value, vdf_data: &mut String, indent_level: usize) {
match json_value { match json_value {
serde_json::Value::Object(obj) => { serde_json::Value::Object(obj) => {
for (key, value) in obj { for (key, value) in obj {
vdf_data.push_str(&"\t".repeat(indent_level)); vdf_data.push_str(&"\t".repeat(indent_level));
vdf_data.push_str(&format!("\"{}\"\n", key)); vdf_data.push_str(&format!("\"{}\"\n", key));
vdf_data.push_str(&"\t".repeat(indent_level)); vdf_data.push_str(&"\t".repeat(indent_level));
vdf_data.push_str("{\n"); vdf_data.push_str("{\n");
build_vdf(value, vdf_data, indent_level + 1); build_vdf(value, vdf_data, indent_level + 1);
vdf_data.push_str(&"\t".repeat(indent_level)); vdf_data.push_str(&"\t".repeat(indent_level));
vdf_data.push_str("}\n"); vdf_data.push_str("}\n");
} }
} }
serde_json::Value::String(s) => { serde_json::Value::String(s) => {
vdf_data.push_str(&"\t".repeat(indent_level)); vdf_data.push_str(&"\t".repeat(indent_level));
vdf_data.push_str(&format!("\"{}\"\t\t\"{}\"\n", s, s)); vdf_data.push_str(&format!("\"{}\"\t\t\"{}\"\n", s, s));
} }
_ => { _ => {
vdf_data.push_str(&"\t".repeat(indent_level)); vdf_data.push_str(&"\t".repeat(indent_level));
vdf_data.push_str(&format!("\"{}\"\t\t\"{}\"\n", json_value, json_value)); vdf_data.push_str(&format!("\"{}\"\t\t\"{}\"\n", json_value, json_value));
} }
} }
} }
mod tests { mod tests {
use super::*; use super::*;
static VDF_DATA: &str = r#""users" static VDF_DATA: &str = r#""users"
{ {
"76561198315078806" "76561198315078806"
{ {
@@ -101,7 +104,7 @@ mod tests {
} }
"#; "#;
static JSON_DATA: &str = r#"{ static JSON_DATA: &str = r#"{
"users": { "users": {
"76561198315078806": { "76561198315078806": {
"AccountName": "_jerry_dota2", "AccountName": "_jerry_dota2",
@@ -126,12 +129,11 @@ mod tests {
} }
}"#; }"#;
#[test] #[test]
fn test_to_json() { fn test_to_json() {
// let expected_json = r#"{"key1": "value1","key2": "value2","subkey": {"key3": "value3"}}"#; // let expected_json = r#"{"key1": "value1","key2": "value2","subkey": {"key3": "value3"}}"#;
let json_data = to_json(VDF_DATA); let json_data = to_json(VDF_DATA);
println!("{}", json_data); println!("{}", json_data);
// 解析json // 解析json
let json_value: serde_json::Value = serde_json::from_str(&json_data).unwrap(); let json_value: serde_json::Value = serde_json::from_str(&json_data).unwrap();
@@ -140,11 +142,11 @@ mod tests {
// assert_eq!(to_json(vdf_data), expected_json); // assert_eq!(to_json(vdf_data), expected_json);
} }
#[test] #[test]
fn test_to_vdf() { fn test_to_vdf() {
// let json_data = r#"{"key1": "value1","key2": "value2","subkey": {"key3": "value3"}}"#; // let json_data = r#"{"key1": "value1","key2": "value2","subkey": {"key3": "value3"}}"#;
let vdf_data = to_vdf(JSON_DATA); let vdf_data = to_vdf(JSON_DATA);
println!("{}", vdf_data); println!("{}", vdf_data);
} }
} }

View File

@@ -1,6 +1,7 @@
use anyhow::Result; use anyhow::Result;
use base64::engine::general_purpose::STANDARD; use base64::engine::general_purpose::STANDARD;
use base64::Engine; use base64::Engine;
use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
@@ -82,40 +83,40 @@ pub struct VideoConfig {
impl Default for VideoConfig { impl Default for VideoConfig {
fn default() -> Self { fn default() -> Self {
VideoConfig { VideoConfig {
version: String::new(), version: "15".to_string(),
vendor_id: String::new(), vendor_id: "0".to_string(),
device_id: String::new(), device_id: "0".to_string(),
cpu_level: String::new(), cpu_level: "3".to_string(),
gpu_mem_level: String::new(), gpu_mem_level: "3".to_string(),
gpu_level: String::new(), gpu_level: "3".to_string(),
knowndevice: String::new(), knowndevice: "0".to_string(),
defaultres: String::new(), defaultres: "1920".to_string(),
defaultresheight: String::new(), defaultresheight: "1080".to_string(),
refreshrate_numerator: String::new(), refreshrate_numerator: "144".to_string(),
refreshrate_denominator: String::new(), refreshrate_denominator: "1".to_string(),
fullscreen: String::new(), fullscreen: "1".to_string(),
coop_fullscreen: String::new(), coop_fullscreen: "0".to_string(),
nowindowborder: String::new(), nowindowborder: "1".to_string(),
mat_vsync: String::new(), mat_vsync: "0".to_string(),
fullscreen_min_on_focus_loss: String::new(), fullscreen_min_on_focus_loss: "1".to_string(),
high_dpi: String::new(), high_dpi: "0".to_string(),
auto_config: String::new(), auto_config: "2".to_string(),
shaderquality: String::new(), shaderquality: "0".to_string(),
r_texturefilteringquality: String::new(), r_texturefilteringquality: "3".to_string(),
msaa_samples: String::new(), msaa_samples: "2".to_string(),
r_csgo_cmaa_enable: String::new(), r_csgo_cmaa_enable: "0".to_string(),
videocfg_shadow_quality: String::new(), videocfg_shadow_quality: "0".to_string(),
videocfg_dynamic_shadows: String::new(), videocfg_dynamic_shadows: "1".to_string(),
videocfg_texture_detail: String::new(), videocfg_texture_detail: "1".to_string(),
videocfg_particle_detail: String::new(), videocfg_particle_detail: "0".to_string(),
videocfg_ao_detail: String::new(), videocfg_ao_detail: "0".to_string(),
videocfg_hdr_detail: String::new(), videocfg_hdr_detail: "3".to_string(),
videocfg_fsr_detail: String::new(), videocfg_fsr_detail: "0".to_string(),
monitor_index: String::new(), monitor_index: "0".to_string(),
r_low_latency: String::new(), r_low_latency: "1".to_string(),
aspectratiomode: String::new(), aspectratiomode: "0".to_string(),
} }
} }
} }
@@ -226,6 +227,9 @@ pub fn parse_local_users(steam_dir: &str) -> Result<Vec<LocalUser>> {
let json_data = super::parse::to_json(&data); let json_data = super::parse::to_json(&data);
let kv: HashMap<String, Value> = serde_json::from_str(&json_data)?; let kv: HashMap<String, Value> = serde_json::from_str(&json_data)?;
// 剥离顶层 UserLocalConfigStore
let kv = kv.get("UserLocalConfigStore").and_then(|v| v.as_object()).unwrap();
// 获取 friends 节点 // 获取 friends 节点
let friends = kv.get("friends").and_then(|v| v.as_object()); let friends = kv.get("friends").and_then(|v| v.as_object());
if friends.is_none() { if friends.is_none() {
@@ -472,108 +476,50 @@ pub fn get_cs2_video(file_path: &str) -> Result<VideoConfig> {
} }
pub fn set_cs2_video(file_path: &str, data: VideoConfig) -> Result<()> { pub fn set_cs2_video(file_path: &str, data: VideoConfig) -> Result<()> {
// TODO: no kv // 读取文件内容
let mut kv = HashMap::new(); let file_content = fs::read_to_string(file_path)?;
kv.insert("version".to_string(), data.version);
kv.insert("vendor_id".to_string(), data.vendor_id);
kv.insert("device_id".to_string(), data.device_id);
kv.insert("setting.cpu_level".to_string(), data.cpu_level);
kv.insert(
"setting.gpu_mem_level".to_string(),
data.gpu_mem_level,
);
kv.insert("setting.gpu_level".to_string(), data.gpu_level);
kv.insert("setting.knowndevice".to_string(), data.knowndevice);
kv.insert("setting.defaultres".to_string(), data.defaultres);
kv.insert(
"setting.defaultresheight".to_string(),
data.defaultresheight,
);
kv.insert(
"setting.refreshrate_numerator".to_string(),
data.refreshrate_numerator,
);
kv.insert(
"setting.refreshrate_denominator".to_string(),
data.refreshrate_denominator,
);
kv.insert("setting.fullscreen".to_string(), data.fullscreen);
kv.insert(
"setting.coop_fullscreen".to_string(),
data.coop_fullscreen,
);
kv.insert(
"setting.nowindowborder".to_string(),
data.nowindowborder,
);
kv.insert("setting.mat_vsync".to_string(), data.mat_vsync);
kv.insert(
"setting.fullscreen_min_on_focus_loss".to_string(),
data.fullscreen_min_on_focus_loss,
);
kv.insert("setting.high_dpi".to_string(), data.high_dpi);
kv.insert("auto_config".to_string(), data.auto_config);
kv.insert(
"setting.shaderquality".to_string(),
data.shaderquality,
);
kv.insert(
"setting.r_texturefilteringquality".to_string(),
data.r_texturefilteringquality,
);
kv.insert(
"setting.msaa_samples".to_string(),
data.msaa_samples,
);
kv.insert(
"setting.r_csgo_cmaa_enable".to_string(),
data.r_csgo_cmaa_enable,
);
kv.insert(
"setting.videocfg_shadow_quality".to_string(),
data.videocfg_shadow_quality,
);
kv.insert(
"setting.videocfg_dynamic_shadows".to_string(),
data.videocfg_dynamic_shadows,
);
kv.insert(
"setting.videocfg_texture_detail".to_string(),
data.videocfg_texture_detail,
);
kv.insert(
"setting.videocfg_particle_detail".to_string(),
data.videocfg_particle_detail,
);
kv.insert(
"setting.videocfg_ao_detail".to_string(),
data.videocfg_ao_detail,
);
kv.insert(
"setting.videocfg_hdr_detail".to_string(),
data.videocfg_hdr_detail,
);
kv.insert(
"setting.videocfg_fsr_detail".to_string(),
data.videocfg_fsr_detail,
);
kv.insert(
"setting.monitor_index".to_string(),
data.monitor_index,
);
kv.insert(
"setting.r_low_latency".to_string(),
data.r_low_latency,
);
kv.insert(
"setting.aspectratiomode".to_string(),
data.aspectratiomode,
);
let json_data = serde_json::to_string(&kv)?; // 定义正则表达式匹配模式
let vdf_data = super::parse::to_vdf(&json_data); let re = Regex::new(r#""(setting\.\w+)"\s+"\d+""#).unwrap();
// println!("{}", vdf_data);
fs::write(file_path, vdf_data)?; // 替换字段值
let updated_content = re.replace_all(&file_content, |caps: &regex::Captures| {
let key = &caps[1]; // 捕获的键名
let value = match key {
"setting.cpu_level" => &data.cpu_level,
"setting.gpu_mem_level" => &data.gpu_mem_level,
"setting.gpu_level" => &data.gpu_level,
"setting.knowndevice" => &data.knowndevice,
"setting.defaultres" => &data.defaultres,
"setting.defaultresheight" => &data.defaultresheight,
"setting.refreshrate_numerator" => &data.refreshrate_numerator,
"setting.refreshrate_denominator" => &data.refreshrate_denominator,
"setting.fullscreen" => &data.fullscreen,
"setting.coop_fullscreen" => &data.coop_fullscreen,
"setting.nowindowborder" => &data.nowindowborder,
"setting.mat_vsync" => &data.mat_vsync,
"setting.fullscreen_min_on_focus_loss" => &data.fullscreen_min_on_focus_loss,
"setting.high_dpi" => &data.high_dpi,
"setting.shaderquality" => &data.shaderquality,
"setting.r_texturefilteringquality" => &data.r_texturefilteringquality,
"setting.msaa_samples" => &data.msaa_samples,
"setting.r_csgo_cmaa_enable" => &data.r_csgo_cmaa_enable,
"setting.videocfg_shadow_quality" => &data.videocfg_shadow_quality,
"setting.videocfg_dynamic_shadows" => &data.videocfg_dynamic_shadows,
"setting.videocfg_texture_detail" => &data.videocfg_texture_detail,
"setting.videocfg_particle_detail" => &data.videocfg_particle_detail,
"setting.videocfg_ao_detail" => &data.videocfg_ao_detail,
"setting.videocfg_hdr_detail" => &data.videocfg_hdr_detail,
"setting.videocfg_fsr_detail" => &data.videocfg_fsr_detail,
"setting.monitor_index" => &data.monitor_index,
"setting.r_low_latency" => &data.r_low_latency,
"setting.aspectratiomode" => &data.aspectratiomode,
_ => "", // 默认情况
};
format!(r#""{}" "{}""#, key, value)
});
fs::write(file_path, updated_content.as_ref())?;
Ok(()) Ok(())
} }
@@ -599,6 +545,11 @@ mod tests {
fn test_set_cs2_video() { fn test_set_cs2_video() {
let manifest_dir = env!("CARGO_MANIFEST_DIR"); let manifest_dir = env!("CARGO_MANIFEST_DIR");
let file_path = format!("{}/temp/cs2_video.txt", manifest_dir); let file_path = format!("{}/temp/cs2_video.txt", manifest_dir);
fs::copy(
format!("{}/src/vdf/tests/cs2_video.txt", manifest_dir),
file_path.clone(),
)
.unwrap();
let video_config = VideoConfig::default(); let video_config = VideoConfig::default();
set_cs2_video(&file_path, video_config).unwrap(); set_cs2_video(&file_path, video_config).unwrap();
} }

View File

@@ -54,13 +54,13 @@ const defaultValue = {
launchIndex: 0, launchIndex: 0,
powerPlan: 0, powerPlan: 0,
videoSetting: { videoSetting: {
version: "1.0", version: "15",
vendor_id: "0x0000", vendor_id: "0",
device_id: "0x0000", device_id: "0",
cpu_level: "3", cpu_level: "3",
gpu_mem_level: "3", gpu_mem_level: "3",
gpu_level: "3", gpu_level: "3",
knowndevice: "Unknown", knowndevice: "0",
defaultres: "1920", defaultres: "1920",
defaultresheight: "1080", defaultresheight: "1080",
refreshrate_numerator: "144", refreshrate_numerator: "144",