use crate::command::Command;
use crate::data::Player as PlayerData;
use crate::message::Message;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt;
use std::fmt::{Display, Formatter};
#[cfg(feature = "raw")]
use crate::command::RawCommand;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "magnus", magnus::wrap(class = "VaultCoh::Player"))]
pub struct Player {
name: String,
human: bool,
faction: Faction,
team: Team,
battlegroup: Option<u32>,
steam_id: Option<u64>,
profile_id: Option<u64>,
messages: Vec<Message>,
commands: Vec<Command>,
#[cfg(feature = "raw")]
raw_commands: Vec<RawCommand>,
}
impl Player {
pub fn name(&self) -> &str {
&self.name
}
pub fn human(&self) -> bool {
self.human
}
pub fn faction(&self) -> Faction {
self.faction
}
pub fn team(&self) -> Team {
self.team
}
pub fn battlegroup(&self) -> Option<u32> {
self.battlegroup
}
pub fn steam_id(&self) -> Option<u64> {
self.steam_id
}
pub fn profile_id(&self) -> Option<u64> {
self.profile_id
}
pub fn messages(&self) -> Vec<Message> {
self.messages.clone()
}
pub fn commands(&self) -> Vec<Command> {
self.commands.clone()
}
#[cfg(feature = "raw")]
pub fn raw_commands(&self) -> Vec<RawCommand> {
self.raw_commands.clone()
}
pub fn build_commands(&self) -> Vec<Command> {
self.commands
.clone()
.into_iter()
.filter(|entry| {
matches!(
entry,
Command::BuildGlobalUpgrade(_) | Command::BuildSquad(_)
)
})
.collect()
}
pub fn battlegroup_commands(&self) -> Vec<Command> {
self.commands
.clone()
.into_iter()
.filter(|entry| {
matches!(
entry,
Command::SelectBattlegroup(_)
| Command::SelectBattlegroupAbility(_)
| Command::UseBattlegroupAbility(_)
)
})
.collect()
}
}
pub(crate) fn player_from_data(
player_data: &PlayerData,
messages: &HashMap<String, Vec<Message>>,
commands: &HashMap<u32, Vec<Command>>,
#[cfg(feature = "raw")] raw_commands: &HashMap<u32, Vec<RawCommand>>,
) -> Player {
let mut player = Player {
name: player_data.name.clone(),
human: player_data.human != 0,
faction: Faction::try_from(player_data.faction.as_ref()).unwrap(),
team: Team::try_from(player_data.team).unwrap(),
steam_id: None,
profile_id: None,
messages: messages.get(&player_data.name).cloned().unwrap_or_default(),
commands: commands.get(&player_data.id).cloned().unwrap_or_default(),
#[cfg(feature = "raw")]
raw_commands: raw_commands
.get(&player_data.id)
.cloned()
.unwrap_or_default(),
battlegroup: None,
};
if player.human {
player.steam_id = Some(str::parse(&player_data.steam_id).unwrap());
player.profile_id = Some(player_data.profile_id);
}
player.battlegroup = match player
.commands
.iter()
.find(|&command| matches!(command, Command::SelectBattlegroup(_)))
{
Some(Command::SelectBattlegroup(command)) => Some(command.pbgid()),
Some(_) => panic!(),
None => None,
};
player
}
impl Display for Player {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}
#[cfg(feature = "magnus")]
unsafe impl magnus::IntoValueFromNative for Player {}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "magnus", magnus::wrap(class = "VaultCoh::Faction"))]
pub enum Faction {
Americans,
British,
Wehrmacht,
AfrikaKorps,
}
impl Display for Faction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Faction::Americans => write!(f, "americans"),
Faction::British => write!(f, "british_africa"),
Faction::Wehrmacht => write!(f, "germans"),
Faction::AfrikaKorps => write!(f, "afrika_korps"),
}
}
}
impl TryFrom<&str> for Faction {
type Error = String;
fn try_from(input: &str) -> Result<Faction, Self::Error> {
match input {
"americans" => Ok(Faction::Americans),
"british" => Ok(Faction::British),
"british_africa" => Ok(Faction::British),
"germans" => Ok(Faction::Wehrmacht),
"afrika_korps" => Ok(Faction::AfrikaKorps),
_ => Err(format!("Invalid faction type {}!", input)),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "magnus", magnus::wrap(class = "VaultCoh::Team"))]
pub enum Team {
First = 0,
Second = 1,
}
impl Team {
pub fn value(&self) -> usize {
*self as usize
}
}
impl TryFrom<u32> for Team {
type Error = String;
fn try_from(input: u32) -> Result<Team, Self::Error> {
match input {
0 => Ok(Team::First),
1 => Ok(Team::Second),
10000 => Ok(Team::Second),
_ => Err(format!("Invalid team ID {}!", input)),
}
}
}