dcso3/
coalition.rs

1/*
2Copyright 2024 Eric Stokes.
3
4This file is part of dcso3.
5
6dcso3 is free software: you can redistribute it and/or modify it under
7the terms of the MIT License.
8
9dcso3 is distributed in the hope that it will be useful, but WITHOUT
10ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE.
12*/
13
14use 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}