flatland3 0.1.0

Flatland3 terminal play client and account CLI
mod api;
mod auth;
mod capabilities;
mod config;
mod game_session;
mod play;
mod terminal;

use clap::{Parser, Subcommand};
use play::PlayArgs;

const ABOUT: &str = "Flatland3 — terminal play client and control-plane CLI";
const LONG_ABOUT: &str = "\
Play a server-authoritative MMORPG in the terminal, or manage accounts via the control plane.

Default (no subcommand): launch the Ratatui play client.

Use `flatland3 capabilities` for a full list of commands and environment variables.";
const AFTER_HELP: &str = "\
EXAMPLES:
  flatland3 auth register --email you@example.com --password '…' --name You
  flatland3 auth login --email you@example.com --password '…'
  flatland3 auth token create --name ci --scope play,read
  flatland3 capabilities              Print capabilities reference

LOCAL DEV (monorepo only):
  cargo run -p flatland-dev -- --bots 4   Embedded server + TUI

SERVICES (local dev):
  make db-up && cargo run -p flatland-control-plane-bin   # HTTP :7380
  cargo run -p flatland-server                            # game :7373
  cargo run -p flatland3                                  # play

See plans/05-cli-and-developer-guide.md for HTTP API and curl examples.";

#[derive(Debug, Parser)]
#[command(
    name = "flatland3",
    version,
    about = ABOUT,
    long_about = LONG_ABOUT,
    after_help = AFTER_HELP
)]
struct Cli {
    #[command(subcommand)]
    command: Option<Command>,

    #[command(flatten)]
    play: PlayArgs,
}

#[derive(Debug, Subcommand)]
enum Command {
    /// Print CLI capabilities, env vars, and quick reference
    Capabilities,
    /// Account login and API token management (control plane HTTP API)
    Auth {
        #[command(subcommand)]
        command: auth::AuthCommand,
    },
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let _ = dotenvy::dotenv();
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| "warn".into()),
        )
        .init();

    let cli = Cli::parse();

    match cli.command {
        Some(Command::Capabilities) => {
            capabilities::print();
            Ok(())
        }
        Some(Command::Auth { command }) => auth::run(command).await,
        None => {
            let opts =
                game_session::prepare_remote_play(&cli.play.name, cli.play.server).await?;
            play::run_with_options(opts).await
        }
    }
}