sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;

/// Sistema de save/load de progresso do jogo.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameSave {
    pub player_data: PlayerData,
    pub game_progress: GameProgress,
    pub settings: GameSettings,
    pub timestamp: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerData {
    pub name: String,
    pub level: u32,
    pub experience: u32,
    pub health: i32,
    pub max_health: i32,
    pub position: (f32, f32),
    pub inventory: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameProgress {
    pub current_level: String,
    pub completed_levels: Vec<String>,
    pub unlocked_abilities: Vec<String>,
    pub score: u32,
    pub playtime_seconds: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameSettings {
    pub music_volume: f32,
    pub sfx_volume: f32,
    pub fullscreen: bool,
    pub difficulty: String,
}

impl GameSave {
    pub fn new() -> Self {
        Self {
            player_data: PlayerData::default(),
            game_progress: GameProgress::default(),
            settings: GameSettings::default(),
            timestamp: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        }
    }

    /// Salva o jogo em formato JSON.
    pub fn save_json<P: AsRef<Path>>(&self, path: P) -> Result<(), String> {
        let json = serde_json::to_string_pretty(self)
            .map_err(|e| format!("Erro ao serializar: {}", e))?;

        fs::write(path, json).map_err(|e| format!("Erro ao escrever arquivo: {}", e))?;

        Ok(())
    }

    /// Carrega o jogo de um arquivo JSON.
    pub fn load_json<P: AsRef<Path>>(path: P) -> Result<Self, String> {
        let content =
            fs::read_to_string(path).map_err(|e| format!("Erro ao ler arquivo: {}", e))?;

        let save: GameSave = serde_json::from_str(&content)
            .map_err(|e| format!("Erro ao deserializar: {}", e))?;

        Ok(save)
    }

    /// Salva o jogo em formato binário (mais compacto).
    pub fn save_binary<P: AsRef<Path>>(&self, path: P) -> Result<(), String> {
        let bytes =
            bincode::serialize(self).map_err(|e| format!("Erro ao serializar: {}", e))?;

        fs::write(path, bytes).map_err(|e| format!("Erro ao escrever arquivo: {}", e))?;

        Ok(())
    }

    /// Carrega o jogo de um arquivo binário.
    pub fn load_binary<P: AsRef<Path>>(path: P) -> Result<Self, String> {
        let bytes = fs::read(path).map_err(|e| format!("Erro ao ler arquivo: {}", e))?;

        let save: GameSave =
            bincode::deserialize(&bytes).map_err(|e| format!("Erro ao deserializar: {}", e))?;

        Ok(save)
    }

    /// Cria um slot de save automático.
    pub fn autosave(&self) -> Result<(), String> {
        self.save_json("saves/autosave.json")
    }

    /// Carrega o save automático.
    pub fn load_autosave() -> Result<Self, String> {
        Self::load_json("saves/autosave.json")
    }

    /// Lista todos os saves disponíveis.
    pub fn list_saves() -> Result<Vec<String>, String> {
        let saves_dir = Path::new("saves");

        if !saves_dir.exists() {
            return Ok(Vec::new());
        }

        let mut saves = Vec::new();

        for entry in fs::read_dir(saves_dir).map_err(|e| format!("Erro ao ler diretório: {}", e))? {
            let entry = entry.map_err(|e| format!("Erro ao ler entrada: {}", e))?;
            let path = entry.path();

            if path.extension().and_then(|s| s.to_str()) == Some("json") {
                if let Some(name) = path.file_stem().and_then(|s| s.to_str()) {
                    saves.push(name.to_string());
                }
            }
        }

        Ok(saves)
    }
}

impl Default for PlayerData {
    fn default() -> Self {
        Self {
            name: "Player".to_string(),
            level: 1,
            experience: 0,
            health: 100,
            max_health: 100,
            position: (0.0, 0.0),
            inventory: Vec::new(),
        }
    }
}

impl Default for GameProgress {
    fn default() -> Self {
        Self {
            current_level: "level1".to_string(),
            completed_levels: Vec::new(),
            unlocked_abilities: Vec::new(),
            score: 0,
            playtime_seconds: 0,
        }
    }
}

impl Default for GameSettings {
    fn default() -> Self {
        Self {
            music_volume: 0.7,
            sfx_volume: 0.8,
            fullscreen: false,
            difficulty: "Normal".to_string(),
        }
    }
}

impl Default for GameSave {
    fn default() -> Self {
        Self::new()
    }
}