1use super::{
15 airbase::Airbase,
16 as_tbl,
17 country::Country,
18 cvt_err, env,
19 group::{Group, GroupCategory},
20 static_object::StaticObject,
21 unit::Unit,
22};
23use crate::{record_perf, simple_enum, wrapped_table, LuaEnv, MizLua, Sequence};
24use anyhow::{anyhow, bail, Result};
25use mlua::{prelude::*, Value};
26use serde_derive::{Deserialize, Serialize};
27use std::{fmt, ops::Deref, str::FromStr};
28
29simple_enum!(Side, u8, [Neutral => 0, Red => 1, Blue => 2]);
30
31impl Default for Side {
32 fn default() -> Self {
33 Side::Red
34 }
35}
36
37impl fmt::Display for Side {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "{}", self.to_str())
40 }
41}
42
43impl FromStr for Side {
44 type Err = anyhow::Error;
45
46 fn from_str(s: &str) -> Result<Self, Self::Err> {
47 Ok(match s {
48 "blue" => Side::Blue,
49 "red" => Side::Red,
50 "neutrals" => Side::Neutral,
51 s => bail!("unknown side {s}"),
52 })
53 }
54}
55
56impl Side {
57 pub const ALL: [Side; 3] = [Side::Red, Side::Blue, Side::Neutral];
58
59 pub fn to_str(&self) -> &'static str {
60 match self {
61 Side::Blue => "blue",
62 Side::Red => "red",
63 Side::Neutral => "neutrals",
64 }
65 }
66
67 pub fn opposite(&self) -> Side {
68 match self {
69 Self::Blue => Self::Red,
70 Self::Red => Self::Blue,
71 Self::Neutral => Self::Neutral,
72 }
73 }
74}
75
76#[derive(Debug, Clone)]
77pub enum Static<'lua> {
78 Airbase(Airbase<'lua>),
79 Static(StaticObject<'lua>),
80}
81
82simple_enum!(Service, u8, [Atc => 0, Awacs => 1, Fac => 3, Tanker => 2]);
83wrapped_table!(Coalition, None);
84
85impl<'lua> Coalition<'lua> {
86 pub fn singleton(lua: MizLua<'lua>) -> Result<Self> {
87 Ok(Self {
88 t: lua.inner().globals().raw_get("coalition")?,
89 lua: lua.inner(),
90 })
91 }
92
93 pub fn add_group(
94 &self,
95 country: Country,
96 category: GroupCategory,
97 data: env::miz::Group<'lua>,
98 ) -> Result<Group<'lua>> {
99 Ok(record_perf!(
100 add_group,
101 self.t
102 .call_function("addGroup", (country, category, data))?
103 ))
104 }
105
106 pub fn add_static_object(
107 &self,
108 country: Country,
109 data: env::miz::Unit<'lua>,
110 ) -> Result<Static<'lua>> {
111 let tbl: LuaTable = record_perf!(
112 add_static_object,
113 self.t.call_function("addStaticObject", (country, data))?
114 );
115 let mt = tbl
116 .get_metatable()
117 .ok_or_else(|| anyhow!("returned static object has no meta table"))?;
118 if mt.raw_get::<_, String>("className_")?.as_str() == "Airbase" {
119 Ok(Static::Airbase(Airbase::from_lua(
120 Value::Table(tbl),
121 self.lua,
122 )?))
123 } else {
124 Ok(Static::Static(StaticObject::from_lua(
125 Value::Table(tbl),
126 self.lua,
127 )?))
128 }
129 }
130
131 pub fn get_groups(&self, side: Side) -> Result<Sequence<'lua, Group<'lua>>> {
132 Ok(self.t.call_function("getGroups", side)?)
133 }
134
135 pub fn get_static_objects(&self, side: Side) -> Result<Sequence<'lua, StaticObject<'lua>>> {
136 Ok(self.t.call_function("getStaticObjects", side)?)
137 }
138
139 pub fn get_airbases(&self, side: Side) -> Result<Sequence<'lua, Airbase<'lua>>> {
140 Ok(self.t.call_function("getAirbases", side)?)
141 }
142
143 pub fn get_players(&self, side: Side) -> Result<Sequence<'lua, Unit<'lua>>> {
144 Ok(self.t.call_function("getPlayers", side)?)
145 }
146
147 pub fn get_service_providers(
148 &self,
149 side: Side,
150 service: Service,
151 ) -> Result<Sequence<'lua, Unit<'lua>>> {
152 Ok(self
153 .t
154 .call_function("getServiceProviders", (side, service))?)
155 }
156
157 pub fn get_country_coalition(&self, country: Country) -> Result<Side> {
158 Ok(self.t.call_function("getCountrySide", country)?)
159 }
160}