mod api;
mod auth;
mod capabilities;
mod config;
mod game_session;
mod inventory;
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 {
#[arg(long, global = true, help = "JSON response envelope for subcommands")]
json: bool,
#[command(subcommand)]
command: Option<Command>,
#[command(flatten)]
play: PlayArgs,
}
#[derive(Debug, Subcommand)]
enum Command {
Capabilities,
Auth {
#[command(subcommand)]
command: auth::AuthCommand,
},
Inventory {
#[arg(long)]
character_id: Option<uuid::Uuid>,
},
}
#[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,
Some(Command::Inventory { character_id }) => inventory::run(character_id, cli.json).await,
None => {
let opts =
game_session::prepare_remote_play(&cli.play.name, cli.play.server).await?;
play::run_with_options(opts).await
}
}
}