spring_ai_rs/ai_interface/callback/
feature_def.rs1use 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}