use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::model::{
location::{ChunkCoordinate, WorldLocation},
named_uuid::{NamedUuid, NamedUuidOpt},
permission::TownyPermissions,
timestamp::Timestamp,
};
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Town {
pub name: String,
pub uuid: Uuid,
pub board: Option<String>,
pub founder: String,
pub wiki: Option<String>,
pub mayor: NamedUuid,
pub nation: NamedUuidOpt,
pub timestamps: TownTimestamps,
pub status: TownStatus,
pub stats: TownStats,
pub perms: TownyPermissions,
pub coordinates: TownCoordinates,
pub residents: Vec<NamedUuid>,
pub trusted: Vec<NamedUuid>,
pub outlaws: Vec<NamedUuid>,
pub quarters: Vec<NamedUuid>,
pub ranks: BTreeMap<TownRankKind, Vec<NamedUuid>>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TownTimestamps {
#[cfg_attr(
feature = "chrono",
serde(with = "crate::model::timestamp::seconds")
)]
pub registered: Timestamp,
#[cfg_attr(
feature = "chrono",
serde(with = "crate::model::timestamp::optional_seconds")
)]
pub joined_nation_at: Option<Timestamp>,
#[cfg_attr(
feature = "chrono",
serde(with = "crate::model::timestamp::optional_seconds")
)]
pub ruined_at: Option<Timestamp>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TownStatus {
pub is_public: bool,
pub is_open: bool,
pub is_neutral: bool,
pub is_capital: bool,
pub is_over_claimed: bool,
pub is_ruined: bool,
pub is_for_sale: bool,
pub has_nation: bool,
pub can_outsiders_spawn: bool,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TownStats {
pub num_town_blocks: i32,
pub max_town_blocks: i32,
pub bonus_blocks: i32,
pub num_residents: i32,
pub num_trusted: i32,
pub num_outlaws: i32,
pub balance: f64,
pub for_sale_price: Option<f64>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TownCoordinates {
pub spawn: WorldLocation,
pub home_block: ChunkCoordinate,
pub town_blocks: Vec<ChunkCoordinate>,
}
#[derive(
Clone, Deserialize, Serialize, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
)]
#[serde(rename_all = "PascalCase")]
pub enum TownRankKind {
Councillor,
Builder,
Recruiter,
Police,
#[serde(rename = "Tax-exempt")]
TaxExempt,
Treasurer,
Realtor,
Settler,
#[serde(untagged)]
Other(String),
}
#[cfg(test)]
mod tests {
use serde_json::json;
use crate::{
endpoints::towns::TownCoordinates,
model::location::{ChunkCoordinate, WorldLocation},
};
fn spawn() -> WorldLocation {
WorldLocation {
world: "earth".to_string(),
x: 1.0,
y: 64.0,
z: 2.0,
pitch: 0.0,
yaw: 90.0,
}
}
#[test]
fn deserializes_town_blocks_from_coordinate_arrays() {
let coordinates: TownCoordinates = serde_json::from_value(json!({
"spawn": {
"world": "earth",
"x": 1.0,
"y": 64.0,
"z": 2.0,
"pitch": 0.0,
"yaw": 90.0
},
"homeBlock": [10, 20],
"townBlocks": [[10, 20], [11, 20]]
}))
.unwrap();
assert_eq!(coordinates.home_block, ChunkCoordinate { x: 10, z: 20 });
assert_eq!(
coordinates.town_blocks,
vec![
ChunkCoordinate { x: 10, z: 20 },
ChunkCoordinate { x: 11, z: 20 },
]
);
}
#[test]
fn serializes_town_blocks_as_coordinate_arrays() {
let coordinates = TownCoordinates {
spawn: spawn(),
home_block: ChunkCoordinate { x: 10, z: 20 },
town_blocks: vec![
ChunkCoordinate { x: 10, z: 20 },
ChunkCoordinate { x: 11, z: 20 },
],
};
assert_eq!(
serde_json::to_value(coordinates).unwrap(),
json!({
"spawn": {
"world": "earth",
"x": 1.0,
"y": 64.0,
"z": 2.0,
"pitch": 0.0,
"yaw": 90.0
},
"homeBlock": [10, 20],
"townBlocks": [[10, 20], [11, 20]]
})
);
}
}