spring_ai_rs/event/
other.rs

1use std::{
2    error::Error,
3    ffi::{CStr, CString},
4};
5
6use slog::{trace, Logger};
7use spring_ai_sys::{
8    SCommandFinishedEvent, SInitEvent, SLoadEvent, SLuaMessageEvent, SMessageEvent,
9    SPlayerCommandEvent, SReleaseEvent, SSaveEvent, SSeismicPingEvent, SUpdateEvent,
10    SWeaponFiredEvent,
11};
12
13use crate::{
14    ai_interface::{
15        callback::{
16            command::command_topic::CommandTopic,
17            group::{init_group_unit_defs, init_group_units},
18            unit::Unit,
19            weapon_def::WeaponDef,
20        },
21        AIInterface,
22    },
23    event::void_to_event,
24    skirmish_ai::{remove_skirmish_ai, set_skirmish_ai, SkirmishAI},
25};
26
27pub struct InitWrapper {
28    pub init_func: InitFuncType,
29}
30
31impl InitWrapper {
32    pub const fn new(init_func: InitFuncType) -> Self {
33        Self { init_func }
34    }
35}
36
37inventory::collect!(InitWrapper);
38
39pub type InitFuncType = fn(&Logger, AIInterface) -> Result<(), Box<dyn Error>>;
40
41pub fn init_wrapper(
42    logger: &Logger,
43    skirmish_ai_id: libc::c_int,
44    data: *const libc::c_void,
45    init_func: &InitFuncType,
46) -> Result<(), Box<dyn Error>> {
47    let init_data = void_to_event::<SInitEvent>(data as *mut libc::c_void)?;
48
49    set_skirmish_ai(skirmish_ai_id, SkirmishAI::new(init_data.callback)?);
50
51    trace!(logger, "AI EVENT INIT");
52
53    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, init_data,);
54
55    init_group_unit_defs(skirmish_ai_id)?;
56    init_group_units(skirmish_ai_id)?;
57
58    init_func(logger, AIInterface::new(skirmish_ai_id))
59}
60
61pub struct ReleaseWrapper {
62    pub release_func: ReleaseFuncType,
63}
64
65impl ReleaseWrapper {
66    pub const fn new(release_func: ReleaseFuncType) -> Self {
67        Self { release_func }
68    }
69}
70
71inventory::collect!(ReleaseWrapper);
72
73pub type ReleaseFuncType = fn(&Logger, AIInterface) -> Result<(), Box<dyn Error>>;
74
75pub fn release_wrapper(
76    logger: &Logger,
77    skirmish_ai_id: libc::c_int,
78    data: *const libc::c_void,
79    release_func: &ReleaseFuncType,
80) -> Result<(), Box<dyn Error>> {
81    let release_data = void_to_event::<SReleaseEvent>(data as *mut libc::c_void)?;
82
83    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, release_data,);
84
85    let ret = release_func(logger, AIInterface::new(skirmish_ai_id));
86
87    remove_skirmish_ai(skirmish_ai_id);
88
89    ret
90}
91
92pub struct MessageWrapper {
93    pub message_func: MessageFuncType,
94}
95
96impl MessageWrapper {
97    pub const fn new(message_func: MessageFuncType) -> Self {
98        Self { message_func }
99    }
100}
101
102inventory::collect!(MessageWrapper);
103
104pub type MessageFuncType = fn(&Logger, AIInterface, i32, &str) -> Result<(), Box<dyn Error>>;
105
106pub fn message_wrapper(
107    logger: &Logger,
108    skirmish_ai_id: libc::c_int,
109    data: *const libc::c_void,
110    message_func: &MessageFuncType,
111) -> Result<(), Box<dyn Error>> {
112    let message_data = void_to_event::<SMessageEvent>(data as *mut libc::c_void)?;
113
114    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, message_data,);
115
116    message_func(
117        logger,
118        AIInterface::new(skirmish_ai_id),
119        message_data.player,
120        unsafe { CStr::from_ptr(message_data.message) }.to_str()?,
121    )
122}
123
124pub struct CommandFinishedWrapper {
125    pub command_finished_func: CommandFinishedFuncType,
126}
127
128impl CommandFinishedWrapper {
129    pub const fn new(command_finished_func: CommandFinishedFuncType) -> Self {
130        Self {
131            command_finished_func,
132        }
133    }
134}
135
136inventory::collect!(CommandFinishedWrapper);
137
138pub type CommandFinishedFuncType =
139    fn(&Logger, AIInterface, Unit, i32, CommandTopic) -> Result<(), Box<dyn Error>>;
140
141pub fn command_finished_wrapper(
142    logger: &Logger,
143    skirmish_ai_id: libc::c_int,
144    data: *const libc::c_void,
145    command_finished_func: &CommandFinishedFuncType,
146) -> Result<(), Box<dyn Error>> {
147    let command_finished_data = void_to_event::<SCommandFinishedEvent>(data as *mut libc::c_void)?;
148
149    trace!(
150        logger,
151        "ID: {}; {:?}",
152        skirmish_ai_id,
153        command_finished_data,
154    );
155
156    command_finished_func(
157        logger,
158        AIInterface::new(skirmish_ai_id),
159        Unit {
160            unit_id: command_finished_data.unitId,
161            ai_id: skirmish_ai_id,
162        },
163        command_finished_data.commandId,
164        CommandTopic::from(command_finished_data.commandTopicId),
165    )
166}
167
168pub struct LoadWrapper {
169    pub load_func: LoadFuncType,
170}
171
172impl LoadWrapper {
173    pub const fn new(load_func: LoadFuncType) -> Self {
174        Self { load_func }
175    }
176}
177
178inventory::collect!(LoadWrapper);
179
180pub type LoadFuncType = fn(&Logger, AIInterface, &str) -> Result<(), Box<dyn Error>>;
181
182pub fn load_wrapper(
183    logger: &Logger,
184    skirmish_ai_id: libc::c_int,
185    data: *const libc::c_void,
186    load_func: &LoadFuncType,
187) -> Result<(), Box<dyn Error>> {
188    let load_data = void_to_event::<SLoadEvent>(data as *mut libc::c_void)?;
189
190    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, load_data);
191
192    load_func(
193        logger,
194        AIInterface::new(skirmish_ai_id),
195        &unsafe { CString::from_raw(load_data.file as *mut _) }.to_string_lossy(),
196    )
197}
198
199pub struct LuaMessageWrapper {
200    pub lua_message_func: LuaMessageFuncType,
201}
202
203impl LuaMessageWrapper {
204    pub const fn new(lua_message_func: LuaMessageFuncType) -> Self {
205        Self { lua_message_func }
206    }
207}
208
209inventory::collect!(LuaMessageWrapper);
210
211pub type LuaMessageFuncType = fn(&Logger, AIInterface, &str) -> Result<(), Box<dyn Error>>;
212
213pub fn lua_message_wrapper(
214    logger: &Logger,
215    skirmish_ai_id: libc::c_int,
216    data: *const libc::c_void,
217    lua_message_func: &LuaMessageFuncType,
218) -> Result<(), Box<dyn Error>> {
219    let lua_message_data = void_to_event::<SLuaMessageEvent>(data as *mut libc::c_void)?;
220
221    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, lua_message_data);
222
223    lua_message_func(
224        logger,
225        AIInterface::new(skirmish_ai_id),
226        &unsafe { CString::from_raw(lua_message_data.inData as *mut _) }.to_string_lossy(),
227    )
228}
229
230pub struct NullWrapper {
231    pub null_func: NullFuncType,
232}
233
234impl NullWrapper {
235    pub const fn new(null_func: NullFuncType) -> Self {
236        Self { null_func }
237    }
238}
239
240inventory::collect!(NullWrapper);
241
242pub type NullFuncType = fn(&Logger, AIInterface) -> Result<(), Box<dyn Error>>;
243
244pub fn null_wrapper(
245    logger: &Logger,
246    skirmish_ai_id: libc::c_int,
247    null_func: &NullFuncType,
248) -> Result<(), Box<dyn Error>> {
249    trace!(logger, "ID: {}", skirmish_ai_id,);
250
251    null_func(logger, AIInterface::new(skirmish_ai_id))
252}
253
254pub struct PlayerCommandWrapper {
255    pub player_command_func: PlayerCommandFuncType,
256}
257
258impl PlayerCommandWrapper {
259    pub const fn new(player_command_func: PlayerCommandFuncType) -> Self {
260        Self {
261            player_command_func,
262        }
263    }
264}
265
266inventory::collect!(PlayerCommandWrapper);
267
268pub type PlayerCommandFuncType =
269    fn(&Logger, AIInterface, &[i32], CommandTopic, i32) -> Result<(), Box<dyn Error>>;
270
271pub fn player_command_wrapper(
272    logger: &Logger,
273    skirmish_ai_id: libc::c_int,
274    data: *const libc::c_void,
275    player_command_func: &PlayerCommandFuncType,
276) -> Result<(), Box<dyn Error>> {
277    let player_command_data = void_to_event::<SPlayerCommandEvent>(data as *mut libc::c_void)?;
278
279    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, player_command_data);
280
281    player_command_func(
282        logger,
283        AIInterface::new(skirmish_ai_id),
284        &unsafe {
285            Vec::from_raw_parts(
286                player_command_data.unitIds,
287                player_command_data.unitIds_size as usize,
288                player_command_data.unitIds_size as usize,
289            )
290        },
291        CommandTopic::from(player_command_data.commandTopicId),
292        player_command_data.playerId,
293    )
294}
295
296pub struct SaveWrapper {
297    pub save_func: SaveFuncType,
298}
299
300impl SaveWrapper {
301    pub const fn new(save_func: SaveFuncType) -> Self {
302        Self { save_func }
303    }
304}
305
306inventory::collect!(SaveWrapper);
307
308pub type SaveFuncType = fn(&Logger, AIInterface, &str) -> Result<(), Box<dyn Error>>;
309
310pub fn save_wrapper(
311    logger: &Logger,
312    skirmish_ai_id: libc::c_int,
313    data: *const libc::c_void,
314    save_func: &SaveFuncType,
315) -> Result<(), Box<dyn Error>> {
316    let save_data = void_to_event::<SSaveEvent>(data as *mut libc::c_void)?;
317
318    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, save_data);
319
320    save_func(
321        logger,
322        AIInterface::new(skirmish_ai_id),
323        &unsafe { CString::from_raw(save_data.file as *mut _) }.to_string_lossy(),
324    )
325}
326
327pub struct SeismicPingWrapper {
328    pub seismic_ping_func: SeismicPingFuncType,
329}
330
331impl SeismicPingWrapper {
332    pub const fn new(seismic_ping_func: SeismicPingFuncType) -> Self {
333        Self { seismic_ping_func }
334    }
335}
336
337inventory::collect!(SeismicPingWrapper);
338
339pub type SeismicPingFuncType =
340    fn(&Logger, AIInterface, [f32; 3], f32) -> Result<(), Box<dyn Error>>;
341
342pub fn seismic_ping_wrapper(
343    logger: &Logger,
344    skirmish_ai_id: libc::c_int,
345    data: *const libc::c_void,
346    seismic_ping_func: &SeismicPingFuncType,
347) -> Result<(), Box<dyn Error>> {
348    let seismic_ping_data = void_to_event::<SSeismicPingEvent>(data as *mut libc::c_void)?;
349
350    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, seismic_ping_data,);
351    let position = unsafe { Vec::from_raw_parts(seismic_ping_data.pos_posF3, 3, 3) };
352
353    seismic_ping_func(
354        logger,
355        AIInterface::new(skirmish_ai_id),
356        [position[0], position[1], position[2]],
357        seismic_ping_data.strength,
358    )
359}
360
361pub struct UpdateWrapper {
362    pub update_func: UpdateFuncType,
363}
364
365impl UpdateWrapper {
366    pub const fn new(update_func: UpdateFuncType) -> Self {
367        Self { update_func }
368    }
369}
370
371inventory::collect!(UpdateWrapper);
372
373pub type UpdateFuncType = fn(&Logger, AIInterface, i32) -> Result<(), Box<dyn Error>>;
374
375pub fn update_wrapper(
376    logger: &Logger,
377    skirmish_ai_id: libc::c_int,
378    data: *const libc::c_void,
379    update_func: &UpdateFuncType,
380) -> Result<(), Box<dyn Error>> {
381    let update_data = void_to_event::<SUpdateEvent>(data as *mut libc::c_void)?;
382
383    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, update_data,);
384
385    update_func(logger, AIInterface::new(skirmish_ai_id), update_data.frame)
386}
387
388pub struct WeaponFiredWrapper {
389    pub weapon_fired_func: WeaponFiredFuncType,
390}
391
392impl WeaponFiredWrapper {
393    pub const fn new(weapon_fired_func: WeaponFiredFuncType) -> Self {
394        Self { weapon_fired_func }
395    }
396}
397
398inventory::collect!(WeaponFiredWrapper);
399
400pub type WeaponFiredFuncType =
401    fn(&Logger, AIInterface, Unit, WeaponDef) -> Result<(), Box<dyn Error>>;
402
403pub fn weapon_fired_wrapper(
404    logger: &Logger,
405    skirmish_ai_id: libc::c_int,
406    data: *const libc::c_void,
407    weapon_fired_func: &WeaponFiredFuncType,
408) -> Result<(), Box<dyn Error>> {
409    let weapon_fired_data = void_to_event::<SWeaponFiredEvent>(data as *mut libc::c_void)?;
410
411    trace!(logger, "ID: {}; {:?}", skirmish_ai_id, weapon_fired_data,);
412
413    weapon_fired_func(
414        logger,
415        AIInterface::new(skirmish_ai_id),
416        Unit {
417            unit_id: weapon_fired_data.unitId,
418            ai_id: skirmish_ai_id,
419        },
420        WeaponDef {
421            weapon_def_id: weapon_fired_data.weaponDefId,
422            ai_id: skirmish_ai_id,
423        },
424    )
425}