use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::process::Command;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameInfo {
pub title: String,
pub sub_title: String,
pub version: Option<String>,
pub cover_urls: Vec<String>,
pub dir_path: PathBuf,
pub start_path: Vec<String>,
pub start_path_defualt: String,
pub description: Option<String>,
pub release_date: DateTime<Utc>,
pub developer: Option<String>,
pub publisher: Option<String>,
pub tabs: Option<String>,
pub platform: Option<String>,
pub byte_size: u64,
pub scan_time: DateTime<Utc>,
pub icon_path: String,
}
impl GameInfo {
pub fn new() -> Self {
GameInfo {
title: String::new(),
sub_title: String::new(),
version: None,
cover_urls: Vec::new(),
dir_path: PathBuf::new(),
start_path: Vec::new(),
start_path_defualt: String::new(),
description: None,
release_date: Utc::now(),
developer: None,
publisher: None,
tabs: None,
platform: None,
byte_size: 0,
scan_time: Utc::now(),
icon_path: String::new(),
}
}
pub fn start_game(&self, index: Option<usize>) -> Result<(bool, String), String> {
if self.start_path.is_empty() {
return Err("游戏没有可启动项".to_string());
}
let start_path = if let Some(idx) = index {
if idx >= self.start_path.len() {
return Err(format!("索引越界: {} (总共 {} 个启动项)", idx, self.start_path.len()));
}
&self.start_path[idx]
} else if !self.start_path_defualt.is_empty() {
&self.start_path_defualt
} else {
&self.start_path[0]
};
let full_path = self.dir_path.join(start_path);
if !full_path.exists() {
return Err(format!("启动项不存在: {}", full_path.display()));
}
match Command::new(&full_path)
.current_dir(&self.dir_path) .spawn()
{
Ok(_child) => {
Ok((true, full_path.display().to_string()))
}
Err(e) => {
Err(format!("启动游戏失败: {} - {}", full_path.display(), e))
}
}
}
}