spring_ai_rs/ai_interface/callback/
feature_def.rs

1use std::{collections::HashMap, error::Error, ffi::CStr};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    ai_interface::{
7        callback::resource::{Resource, ResourceInterface},
8        AIInterface,
9    },
10    get_callback,
11};
12
13#[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
14pub struct FeatureDef {
15    pub ai_id: i32,
16    pub feature_def_id: i32,
17}
18
19#[derive(Debug, Clone)]
20pub struct FeatureDefInterface {
21    pub ai_id: i32,
22}
23
24#[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
25pub enum FeatureDefResurrectable {
26    Yes,
27    No,
28    Err,
29}
30
31#[derive(Debug, Clone)]
32pub struct FeatureDefAll {
33    name: String,
34    description: String,
35    contained_resource: HashMap<Resource, f32>,
36    reclaim_time: f32,
37    mass: f32,
38    upright: bool,
39    draw_type: i32,
40    resurrectable: FeatureDefResurrectable,
41    smoke_time: i32,
42    destructable: bool,
43    reclaimable: bool,
44    blocking: bool,
45    burnable: bool,
46    floating: bool,
47    no_select: bool,
48    geo_thermal: bool,
49    x_size: i32,
50    z_size: i32,
51}
52
53impl AIInterface {
54    pub fn feature_def_interface(&self) -> FeatureDefInterface {
55        FeatureDefInterface { ai_id: self.ai_id }
56    }
57}
58
59const MAX_FEATURE_DEFS: usize = 128;
60
61impl FeatureDefInterface {
62    pub fn get_feature_defs(&self) -> Result<Vec<FeatureDef>, Box<dyn Error>> {
63        let get_feature_defs = get_callback!(self.ai_id, getFeatureDefs)?;
64
65        let mut ret = [-1_i32; MAX_FEATURE_DEFS];
66        unsafe { get_feature_defs(self.ai_id, ret.as_mut_ptr(), MAX_FEATURE_DEFS as i32) };
67
68        Ok(ret
69            .iter()
70            .filter_map(|&i| {
71                if i == -1 {
72                    None
73                } else {
74                    Some(FeatureDef {
75                        ai_id: self.ai_id,
76                        feature_def_id: i,
77                    })
78                }
79            })
80            .collect())
81    }
82}
83
84impl FeatureDef {
85    pub fn name(&self) -> Result<String, Box<dyn Error>> {
86        let get_name = get_callback!(self.ai_id, FeatureDef_getName)?;
87        Ok(String::from(
88            unsafe { CStr::from_ptr(get_name(self.ai_id, self.feature_def_id)) }.to_str()?,
89        ))
90    }
91
92    pub fn description(&self) -> Result<String, Box<dyn Error>> {
93        let get_description = get_callback!(self.ai_id, FeatureDef_getDescription)?;
94        Ok(String::from(
95            unsafe { CStr::from_ptr(get_description(self.ai_id, self.feature_def_id)) }.to_str()?,
96        ))
97    }
98
99    pub fn contained_resource(&self) -> Result<HashMap<Resource, f32>, Box<dyn Error>> {
100        let get_contained_resource = get_callback!(self.ai_id, FeatureDef_getContainedResource)?;
101        Ok(ResourceInterface { ai_id: self.ai_id }
102            .get_resources()?
103            .into_iter()
104            .map(|resource| {
105                (resource, unsafe {
106                    get_contained_resource(self.ai_id, self.feature_def_id, resource.resource_id)
107                })
108            })
109            .collect())
110    }
111
112    pub fn max_health(&self) -> Result<f32, Box<dyn Error>> {
113        let get_max_health = get_callback!(self.ai_id, FeatureDef_getMaxHealth)?;
114        Ok(unsafe { get_max_health(self.ai_id, self.feature_def_id) })
115    }
116
117    pub fn reclaim_time(&self) -> Result<f32, Box<dyn Error>> {
118        let get_reclaim_time = get_callback!(self.ai_id, FeatureDef_getReclaimTime)?;
119        Ok(unsafe { get_reclaim_time(self.ai_id, self.feature_def_id) })
120    }
121
122    pub fn mass(&self) -> Result<f32, Box<dyn Error>> {
123        let get_mass = get_callback!(self.ai_id, FeatureDef_getMass)?;
124        Ok(unsafe { get_mass(self.ai_id, self.feature_def_id) })
125    }
126
127    pub fn upright(&self) -> Result<bool, Box<dyn Error>> {
128        let get_is_upright = get_callback!(self.ai_id, FeatureDef_isUpright)?;
129        Ok(unsafe { get_is_upright(self.ai_id, self.feature_def_id) })
130    }
131
132    pub fn draw_type(&self) -> Result<i32, Box<dyn Error>> {
133        let get_draw_type = get_callback!(self.ai_id, FeatureDef_getDrawType)?;
134        Ok(unsafe { get_draw_type(self.ai_id, self.feature_def_id) })
135    }
136
137    pub fn resurrectable(&self) -> Result<FeatureDefResurrectable, Box<dyn Error>> {
138        let get_resurrectable = get_callback!(self.ai_id, FeatureDef_getResurrectable)?;
139        Ok(
140            match unsafe { get_resurrectable(self.ai_id, self.feature_def_id) } {
141                0 => FeatureDefResurrectable::No,
142                1 => FeatureDefResurrectable::Yes,
143                _ => FeatureDefResurrectable::Err,
144            },
145        )
146    }
147
148    pub fn smoke_time(&self) -> Result<i32, Box<dyn Error>> {
149        let get_smoke_time = get_callback!(self.ai_id, FeatureDef_getSmokeTime)?;
150        Ok(unsafe { get_smoke_time(self.ai_id, self.feature_def_id) })
151    }
152
153    pub fn destructable(&self) -> Result<bool, Box<dyn Error>> {
154        let get_is_destructable = get_callback!(self.ai_id, FeatureDef_isDestructable)?;
155        Ok(unsafe { get_is_destructable(self.ai_id, self.feature_def_id) })
156    }
157
158    pub fn reclaimable(&self) -> Result<bool, Box<dyn Error>> {
159        let get_is_reclaimable = get_callback!(self.ai_id, FeatureDef_isReclaimable)?;
160        Ok(unsafe { get_is_reclaimable(self.ai_id, self.feature_def_id) })
161    }
162
163    pub fn blocking(&self) -> Result<bool, Box<dyn Error>> {
164        let get_is_blocking = get_callback!(self.ai_id, FeatureDef_isBlocking)?;
165        Ok(unsafe { get_is_blocking(self.ai_id, self.feature_def_id) })
166    }
167
168    pub fn burnable(&self) -> Result<bool, Box<dyn Error>> {
169        let get_is_burnable = get_callback!(self.ai_id, FeatureDef_isBurnable)?;
170        Ok(unsafe { get_is_burnable(self.ai_id, self.feature_def_id) })
171    }
172
173    pub fn floating(&self) -> Result<bool, Box<dyn Error>> {
174        let get_is_floating = get_callback!(self.ai_id, FeatureDef_isFloating)?;
175        Ok(unsafe { get_is_floating(self.ai_id, self.feature_def_id) })
176    }
177
178    pub fn no_select(&self) -> Result<bool, Box<dyn Error>> {
179        let get_is_no_select = get_callback!(self.ai_id, FeatureDef_isNoSelect)?;
180        Ok(unsafe { get_is_no_select(self.ai_id, self.feature_def_id) })
181    }
182
183    pub fn geo_thermal(&self) -> Result<bool, Box<dyn Error>> {
184        let get_is_geo_thermal = get_callback!(self.ai_id, FeatureDef_isGeoThermal)?;
185        Ok(unsafe { get_is_geo_thermal(self.ai_id, self.feature_def_id) })
186    }
187
188    pub fn x_size(&self) -> Result<i32, Box<dyn Error>> {
189        let get_x_size = get_callback!(self.ai_id, FeatureDef_getXSize)?;
190        Ok(unsafe { get_x_size(self.ai_id, self.feature_def_id) })
191    }
192
193    pub fn z_size(&self) -> Result<i32, Box<dyn Error>> {
194        let get_z_size = get_callback!(self.ai_id, FeatureDef_getZSize)?;
195        Ok(unsafe { get_z_size(self.ai_id, self.feature_def_id) })
196    }
197
198    pub fn all(&self) -> Result<FeatureDefAll, Box<dyn Error>> {
199        Ok(FeatureDefAll {
200            name: self.name()?,
201            description: self.description()?,
202            contained_resource: self.contained_resource()?,
203            reclaim_time: self.reclaim_time()?,
204            mass: self.mass()?,
205            upright: self.upright()?,
206            draw_type: self.draw_type()?,
207            resurrectable: self.resurrectable()?,
208            smoke_time: self.smoke_time()?,
209            destructable: self.destructable()?,
210            reclaimable: self.reclaimable()?,
211            blocking: self.blocking()?,
212            burnable: self.burnable()?,
213            floating: self.floating()?,
214            no_select: self.no_select()?,
215            geo_thermal: self.geo_thermal()?,
216            x_size: self.x_size()?,
217            z_size: self.z_size()?,
218        })
219    }
220}