flatland3 0.1.0

Flatland3 terminal play client and account CLI
use flatland_protocol::AuthCredential;
use uuid::Uuid;

use crate::api::ControlPlaneClient;
use crate::config::SessionConfig;
use flatland_client_lib::ConnectOptions;

#[derive(serde::Deserialize)]
struct CharacterList {
    characters: Vec<CharacterRow>,
}

#[derive(serde::Deserialize)]
struct CharacterRow {
    id: Uuid,
    name: String,
}

#[derive(serde::Deserialize)]
struct CreateCharacter {
    character: CharacterRow,
}

/// Resolve session + character for authenticated remote play.
pub async fn prepare_remote_play(
    character_name: &str,
    server: std::net::SocketAddr,
) -> anyhow::Result<ConnectOptions> {
    let session = SessionConfig::load()?;
    let client = ControlPlaneClient::new(&session.api_base);

    let list: CharacterList = client
        .get("/v1/characters", &session.session_token)
        .await?;

    let character = if let Some(existing) = list
        .characters
        .into_iter()
        .find(|c| c.name == character_name)
    {
        existing
    } else {
        let created: CreateCharacter = client
            .post(
                "/v1/characters",
                &serde_json::json!({ "name": character_name }),
                Some(&session.session_token),
            )
            .await?;
        created.character
    };

    Ok(
        ConnectOptions::to_server(&character.name, server).with_auth(
            AuthCredential::Session {
                token: session.session_token,
            },
            Some(character.id),
        ),
    )
}