flatland3 0.2.1

Flatland3 terminal play client and account CLI
use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionConfig {
    pub api_base: String,
    pub session_token: String,
    /// Last character used for play — preferred over name matching on reconnect.
    #[serde(default)]
    pub last_character_id: Option<Uuid>,
}

impl SessionConfig {
    pub fn path() -> anyhow::Result<PathBuf> {
        let base = dirs::config_dir()
            .ok_or_else(|| anyhow::anyhow!("could not resolve config directory"))?;
        Ok(base.join("flatland").join("session.json"))
    }

    pub fn load() -> anyhow::Result<Self> {
        let path = Self::path()?;
        let bytes = std::fs::read(&path)
            .map_err(|_| anyhow::anyhow!("not logged in; run `flatland3 auth login`"))?;
        Ok(serde_json::from_slice(&bytes)?)
    }

    pub fn save(&self) -> anyhow::Result<()> {
        let path = Self::path()?;
        if let Some(parent) = path.parent() {
            std::fs::create_dir_all(parent)?;
        }
        std::fs::write(path, serde_json::to_vec_pretty(self)?)?;
        Ok(())
    }

    pub fn remember_character(&mut self, character_id: Uuid) -> anyhow::Result<()> {
        if self.last_character_id == Some(character_id) {
            return Ok(());
        }
        self.last_character_id = Some(character_id);
        self.save()
    }
}

pub fn default_api_base() -> String {
    std::env::var("FLATLAND_API_URL").unwrap_or_else(|_| "http://127.0.0.1:7380".into())
}