use uuid::Uuid;
use crate::api::ControlPlaneClient;
use crate::config::SessionConfig;
use crate::inventory::{InventoryItem, InventoryOutput};
#[derive(Debug, clap::Subcommand)]
pub enum PlotCommand {
Deeds {
#[arg(long)]
character_id: Option<Uuid>,
},
}
pub async fn run(command: PlotCommand, json: bool) -> anyhow::Result<()> {
match command {
PlotCommand::Deeds { character_id } => list_deeds(character_id, json).await,
}
}
async fn list_deeds(character_id: Option<Uuid>, json: bool) -> anyhow::Result<()> {
let session = SessionConfig::load()?;
let client = ControlPlaneClient::new(&session.api_base);
#[derive(serde::Deserialize)]
struct CharacterList {
characters: Vec<CharacterRow>,
}
#[derive(serde::Deserialize)]
struct CharacterRow {
id: Uuid,
}
let character_id = match character_id {
Some(id) => id,
None => {
let list: CharacterList = client.get("/v1/characters", &session.session_token).await?;
list.characters
.first()
.map(|c| c.id)
.ok_or_else(|| anyhow::anyhow!("no characters — run flatland3 auth register"))?
}
};
#[derive(serde::Deserialize)]
struct InventoryResponse {
character_id: Uuid,
items: Vec<InventoryItem>,
}
let inv: InventoryResponse = client
.get(
&format!("/v1/characters/{character_id}/inventory"),
&session.session_token,
)
.await?;
let deeds: Vec<&InventoryItem> = inv
.items
.iter()
.filter(|i| i.template_id == "property_deed")
.collect();
if json {
let data = InventoryOutput {
character_id: inv.character_id,
items: deeds.into_iter().cloned().collect(),
};
println!(
"{}",
serde_json::to_string_pretty(&serde_json::json!({
"ok": true,
"data": data
}))?
);
} else if deeds.is_empty() {
println!(
"No property deeds for {} — claim a plot in gfx (f on free property land).",
inv.character_id
);
} else {
println!("Property deeds for {}:", inv.character_id);
for d in deeds {
println!(" {} ({})", d.template_id, d.item_instance_id);
}
println!("Buy/sell plots in-game via claim mode (see docs/property-plots.md).");
}
Ok(())
}