spring_ai_rs/ai_interface/callback/unit/
command.rs

1use std::error::Error;
2
3use spring_ai_sys::COMMAND_TO_ID_ENGINE;
4
5use crate::ai_interface::callback::{
6    command::{
7        command_data::{
8            unit::{
9                AiSelectUnitCommandData, AttackAreaUnitCommandData, AttackUnitCommandData,
10                BuildUnitCommandData, CaptureAreaUnitCommanddData, CaptureUnitCommanddData,
11                CloakUnitCommandData, CustomUnitCommanddData, DGunUnitCommandData,
12                FightUnitCommandData, GuardUnitCommandData, LoadOntoUnitCommandData,
13                LoadUnitsAreaCommandData, LoadUnitsUnitCommandData, MoveUnitCommandData,
14                PatrolUnitCommandData, ReclaimAreaUnitCommandData, ReclaimFeatureUnitCommandData,
15                ReclaimUnitUnitCommandData, RepairUnitCommandData, RestoreAreaUnitCommandData,
16                ResurrectAreaUnitCommandData, ResurrectUnitCommandData, SelfDestroyUnitCommandData,
17                SetAutoRepairLevelUnitCommandData, SetBaseUnitCommandData, SetFireUnitCommandData,
18                SetIdleModeCommandData, SetMoveStateCommandData, SetUnitOnOffCommandData,
19                SetUnitRepeatCommandData, SetUnitStockpileCommandData, SetUnitStopCommandData,
20                SetUnitTrajectoryCommandData, SetUnitUnloadAreaCommandData,
21                SetUnitUnloadCommandData, SetUnitWaitCommandData, SetUnitWaitGatherCommandData,
22                SetUnitWaitSquadCommandData, SetUnitWaitTimeCommandData,
23            },
24            CommandData,
25        },
26        command_topic::CommandTopic,
27        options::UnitCommandOptions,
28    },
29    engine::handle_command,
30    facing::Facing,
31    feature::Feature,
32    fire_state::FireState,
33    idle_mode::IdleMode,
34    move_state::MoveState,
35    position::Position,
36    trajectory::Trajectory,
37    unit::Unit,
38    unit_def::UnitDef,
39};
40
41impl Unit {
42    pub fn select(
43        &self,
44        options: &[UnitCommandOptions],
45        command_id: Option<i32>,
46        timeout: Option<i32>,
47    ) -> Result<(), &'static str> {
48        let mut command_data = AiSelectUnitCommandData {
49            unit_id: self.unit_id,
50            group_id: -1,
51            options: options.to_vec(),
52            timeout: timeout.unwrap_or(i32::MAX),
53        };
54
55        handle_command(
56            self.ai_id,
57            COMMAND_TO_ID_ENGINE,
58            command_id.unwrap_or(-1),
59            CommandTopic::UnitAISelect.into(),
60            &mut command_data.c_data(),
61        )
62    }
63
64    pub fn attack(
65        &self,
66        options: &[UnitCommandOptions],
67        command_id: Option<i32>,
68        timeout: Option<i32>,
69        target: Unit,
70    ) -> Result<(), &'static str> {
71        let mut command_data = AttackUnitCommandData {
72            unit_id: self.unit_id,
73            group_id: -1,
74            options: options.to_vec(),
75            timeout: timeout.unwrap_or(i32::MAX),
76            target_unit_id: target.unit_id,
77        };
78
79        handle_command(
80            self.ai_id,
81            COMMAND_TO_ID_ENGINE,
82            command_id.unwrap_or(-1),
83            CommandTopic::UnitAttack.into(),
84            &mut command_data.c_data(),
85        )
86    }
87
88    pub fn attack_area(
89        &self,
90        options: &[UnitCommandOptions],
91        command_id: Option<i32>,
92        timeout: Option<i32>,
93        position: [f32; 3],
94        radius: f32,
95    ) -> Result<(), &'static str> {
96        let mut command_data = AttackAreaUnitCommandData {
97            unit_id: self.unit_id,
98            group_id: -1,
99            options: options.to_vec(),
100            timeout: timeout.unwrap_or(i32::MAX),
101            attack_position: position,
102            radius,
103        };
104
105        handle_command(
106            self.ai_id,
107            COMMAND_TO_ID_ENGINE,
108            command_id.unwrap_or(-1),
109            CommandTopic::UnitAttackArea.into(),
110            &mut command_data.c_data(),
111        )
112    }
113
114    pub fn build<P: Position, D: PartialEq<UnitDef>>(
115        &self,
116        options: &[UnitCommandOptions],
117        command_id: Option<i32>,
118        timeout: Option<i32>,
119        to_build_unit_def: D,
120        position: P,
121        facing: Facing,
122    ) -> Result<(), Box<dyn Error>> {
123        let mut building_def_opt = None;
124        for unit_def in self.unit_def()?.building().build_options()? {
125            if to_build_unit_def == unit_def {
126                building_def_opt = Some(unit_def);
127            }
128        }
129
130        if let Some(building_def) = building_def_opt {
131            let building_x = building_def.miscellaneous().x_size()?;
132            let building_z = building_def.miscellaneous().z_size()?;
133
134            let mut build_position = position.to_f32_array(self.ai_id)?;
135            build_position[0] =
136                ((build_position[0] + (building_x as f32 / 2.0)) / 16.0).trunc() * 16.0;
137            build_position[2] =
138                ((build_position[2] + (building_z as f32 / 2.0)) / 16.0).trunc() * 16.0;
139
140            let mut command_data = BuildUnitCommandData {
141                unit_id: self.unit_id,
142                group_id: -1,
143                options: options.to_vec(),
144                timeout: timeout.unwrap_or(i32::MAX),
145                to_build_unit_def_id: building_def.def_id,
146                build_position,
147                facing,
148            };
149
150            handle_command(
151                self.ai_id,
152                COMMAND_TO_ID_ENGINE,
153                command_id.unwrap_or(-1),
154                CommandTopic::UnitBuild.into(),
155                &mut command_data.c_data(),
156            )?;
157        }
158
159        Ok(())
160    }
161
162    pub fn capture(
163        &self,
164        options: &[UnitCommandOptions],
165        command_id: Option<i32>,
166        timeout: Option<i32>,
167        target: Unit,
168    ) -> Result<(), &'static str> {
169        let mut command_data = CaptureUnitCommanddData {
170            unit_id: self.unit_id,
171            group_id: -1,
172            options: options.to_vec(),
173            timeout: timeout.unwrap_or(i32::MAX),
174            to_capture_unit_id: target.unit_id,
175        };
176
177        handle_command(
178            self.ai_id,
179            COMMAND_TO_ID_ENGINE,
180            command_id.unwrap_or(-1),
181            CommandTopic::UnitCapture.into(),
182            &mut command_data.c_data(),
183        )
184    }
185
186    pub fn capture_area(
187        &self,
188        options: &[UnitCommandOptions],
189        command_id: Option<i32>,
190        timeout: Option<i32>,
191        position: [f32; 3],
192        radius: f32,
193    ) -> Result<(), &'static str> {
194        let mut command_data = CaptureAreaUnitCommanddData {
195            unit_id: self.unit_id,
196            group_id: -1,
197            options: options.to_vec(),
198            timeout: timeout.unwrap_or(i32::MAX),
199            position,
200            radius,
201        };
202
203        handle_command(
204            self.ai_id,
205            COMMAND_TO_ID_ENGINE,
206            command_id.unwrap_or(-1),
207            CommandTopic::UnitCaptureArea.into(),
208            &mut command_data.c_data(),
209        )
210    }
211
212    pub fn cloak(
213        &self,
214        options: &[UnitCommandOptions],
215        command_id: Option<i32>,
216        timeout: Option<i32>,
217        cloak: bool,
218    ) -> Result<(), &'static str> {
219        let mut command_data = CloakUnitCommandData {
220            unit_id: self.unit_id,
221            group_id: -1,
222            options: options.to_vec(),
223            timeout: timeout.unwrap_or(i32::MAX),
224            cloak,
225        };
226
227        handle_command(
228            self.ai_id,
229            COMMAND_TO_ID_ENGINE,
230            command_id.unwrap_or(-1),
231            CommandTopic::UnitCloak.into(),
232            &mut command_data.c_data(),
233        )
234    }
235
236    pub fn custom_command(
237        &self,
238        options: &[UnitCommandOptions],
239        command_id: Option<i32>,
240        timeout: Option<i32>,
241        parameters: Vec<f32>,
242    ) -> Result<(), &'static str> {
243        let mut command_data = CustomUnitCommanddData {
244            unit_id: self.unit_id,
245            group_id: -1,
246            options: options.to_vec(),
247            timeout: timeout.unwrap_or(i32::MAX),
248            command_id: command_id.unwrap_or(-1),
249            parameters,
250        };
251
252        handle_command(
253            self.ai_id,
254            COMMAND_TO_ID_ENGINE,
255            command_id.unwrap_or(-1),
256            CommandTopic::UnitCustom.into(),
257            &mut command_data.c_data(),
258        )
259    }
260
261    pub fn dgun_unit(
262        &self,
263        options: &[UnitCommandOptions],
264        command_id: Option<i32>,
265        timeout: Option<i32>,
266        target: Unit,
267    ) -> Result<(), &'static str> {
268        let mut command_data = DGunUnitCommandData {
269            unitId: self.unit_id,
270            groupId: -1,
271            options: options.to_vec(),
272            timeOut: timeout.unwrap_or(i32::MAX),
273            toAttackUnitId: target.unit_id,
274        };
275
276        handle_command(
277            self.ai_id,
278            COMMAND_TO_ID_ENGINE,
279            command_id.unwrap_or(-1),
280            CommandTopic::UnitDGun.into(),
281            &mut command_data.c_data(),
282        )
283    }
284
285    pub fn fight<P: Position>(
286        &self,
287        options: &[UnitCommandOptions],
288        command_id: Option<i32>,
289        timeout: Option<i32>,
290        position: P,
291    ) -> Result<(), &'static str> {
292        let mut command_data = FightUnitCommandData {
293            unitId: self.unit_id,
294            groupId: -1,
295            options: options.to_vec(),
296            timeOut: timeout.unwrap_or(i32::MAX),
297            position: position.to_f32_array(self.ai_id).unwrap(),
298        };
299
300        handle_command(
301            self.ai_id,
302            COMMAND_TO_ID_ENGINE,
303            command_id.unwrap_or(-1),
304            CommandTopic::UnitFight.into(),
305            &mut command_data.c_data(),
306        )
307    }
308
309    pub fn guard(
310        &self,
311        options: &[UnitCommandOptions],
312        command_id: Option<i32>,
313        timeout: Option<i32>,
314        target: Unit,
315    ) -> Result<(), &'static str> {
316        let mut command_data = GuardUnitCommandData {
317            unitId: self.unit_id,
318            groupId: -1,
319            options: options.to_vec(),
320            timeOut: timeout.unwrap_or(i32::MAX),
321            to_guard_unit_id: target.unit_id,
322        };
323
324        handle_command(
325            self.ai_id,
326            COMMAND_TO_ID_ENGINE,
327            command_id.unwrap_or(-1),
328            CommandTopic::UnitGuard.into(),
329            &mut command_data.c_data(),
330        )
331    }
332
333    pub fn load_onto(
334        &self,
335        options: &[UnitCommandOptions],
336        command_id: Option<i32>,
337        timeout: Option<i32>,
338        target: Unit,
339    ) -> Result<(), &'static str> {
340        let mut command_data = LoadOntoUnitCommandData {
341            unitId: self.unit_id,
342            groupId: -1,
343            options: options.to_vec(),
344            timeOut: timeout.unwrap_or(i32::MAX),
345            transporter_unit_id: target.unit_id,
346        };
347
348        handle_command(
349            self.ai_id,
350            COMMAND_TO_ID_ENGINE,
351            command_id.unwrap_or(-1),
352            CommandTopic::UnitLoadOnto.into(),
353            &mut command_data.c_data(),
354        )
355    }
356
357    pub fn load_units(
358        &self,
359        options: &[UnitCommandOptions],
360        command_id: Option<i32>,
361        timeout: Option<i32>,
362        targets: &[Unit],
363    ) -> Result<(), &'static str> {
364        let mut command_data = LoadUnitsUnitCommandData {
365            unitId: self.unit_id,
366            groupId: -1,
367            options: options.to_vec(),
368            timeOut: timeout.unwrap_or(i32::MAX),
369            to_load_unit_ids: targets.iter().map(|t| t.unit_id).collect(),
370        };
371
372        handle_command(
373            self.ai_id,
374            COMMAND_TO_ID_ENGINE,
375            command_id.unwrap_or(-1),
376            CommandTopic::UnitLoadUnits.into(),
377            &mut command_data.c_data(),
378        )
379    }
380
381    pub fn load_units_area(
382        &self,
383        options: &[UnitCommandOptions],
384        command_id: Option<i32>,
385        timeout: Option<i32>,
386        position: [f32; 3],
387        radius: f32,
388    ) -> Result<(), &'static str> {
389        let mut command_data = LoadUnitsAreaCommandData {
390            unitId: self.unit_id,
391            groupId: -1,
392            options: options.to_vec(),
393            timeOut: timeout.unwrap_or(i32::MAX),
394            position,
395            radius,
396        };
397
398        handle_command(
399            self.ai_id,
400            COMMAND_TO_ID_ENGINE,
401            command_id.unwrap_or(-1),
402            CommandTopic::UnitLoadUnitsArea.into(),
403            &mut command_data.c_data(),
404        )
405    }
406
407    pub fn move_unit<P: Position>(
408        &self,
409        options: &[UnitCommandOptions],
410        command_id: Option<i32>,
411        timeout: Option<i32>,
412        to_pos: P,
413    ) -> Result<(), Box<dyn Error>> {
414        let mut command_data = MoveUnitCommandData {
415            unit_id: self.unit_id,
416            group_id: -1,
417            options: options.to_vec(),
418            timeout: timeout.unwrap_or(i32::MAX),
419            to_pos: to_pos.to_f32_array(self.ai_id)?,
420        };
421
422        handle_command(
423            self.ai_id,
424            COMMAND_TO_ID_ENGINE,
425            command_id.unwrap_or(-1),
426            CommandTopic::UnitMove.into(),
427            &mut command_data.c_data(),
428        )?;
429
430        Ok(())
431    }
432
433    pub fn patrol<P: Position>(
434        &self,
435        options: &[UnitCommandOptions],
436        command_id: Option<i32>,
437        timeout: Option<i32>,
438        to_pos: P,
439    ) -> Result<(), Box<dyn Error>> {
440        let mut command_data = PatrolUnitCommandData {
441            unit_id: self.unit_id,
442            group_id: -1,
443            options: options.to_vec(),
444            timeout: timeout.unwrap_or(i32::MAX),
445            to_pos: to_pos.to_f32_array(self.ai_id)?,
446        };
447
448        handle_command(
449            self.ai_id,
450            COMMAND_TO_ID_ENGINE,
451            command_id.unwrap_or(-1),
452            CommandTopic::UnitPatrol.into(),
453            &mut command_data.c_data(),
454        )?;
455
456        Ok(())
457    }
458
459    pub fn reclaim_area<P: Position>(
460        &self,
461        options: &[UnitCommandOptions],
462        command_id: Option<i32>,
463        timeout: Option<i32>,
464        position: P,
465        radius: f32,
466    ) -> Result<(), &'static str> {
467        let mut command_data = ReclaimAreaUnitCommandData {
468            unit_id: self.unit_id,
469            group_id: -1,
470            options: options.to_vec(),
471            timeout: timeout.unwrap_or(i32::MAX),
472            position: position.to_f32_array(self.ai_id).unwrap(),
473            radius,
474        };
475
476        handle_command(
477            self.ai_id,
478            COMMAND_TO_ID_ENGINE,
479            command_id.unwrap_or(-1),
480            CommandTopic::UnitReclaimArea.into(),
481            &mut command_data.c_data(),
482        )
483    }
484
485    pub fn reclaim_feature(
486        &self,
487        options: &[UnitCommandOptions],
488        command_id: Option<i32>,
489        timeout: Option<i32>,
490        target: Feature,
491    ) -> Result<(), &'static str> {
492        let mut command_data = ReclaimFeatureUnitCommandData {
493            unit_id: self.unit_id,
494            group_id: -1,
495            options: options.to_vec(),
496            timeout: timeout.unwrap_or(i32::MAX),
497            to_reclaim_feature_id: target.feature_id,
498        };
499
500        handle_command(
501            self.ai_id,
502            COMMAND_TO_ID_ENGINE,
503            command_id.unwrap_or(-1),
504            CommandTopic::UnitReclaimFeature.into(),
505            &mut command_data.c_data(),
506        )
507    }
508
509    pub fn reclaim_unit(
510        &self,
511        options: &[UnitCommandOptions],
512        command_id: Option<i32>,
513        timeout: Option<i32>,
514        target: Unit,
515    ) -> Result<(), &'static str> {
516        let mut command_data = ReclaimUnitUnitCommandData {
517            unit_id: self.unit_id,
518            group_id: -1,
519            options: options.to_vec(),
520            timeout: timeout.unwrap_or(i32::MAX),
521            to_reclaim_unit_id: target.unit_id,
522        };
523
524        handle_command(
525            self.ai_id,
526            COMMAND_TO_ID_ENGINE,
527            command_id.unwrap_or(-1),
528            CommandTopic::UnitReclaimFeature.into(),
529            &mut command_data.c_data(),
530        )
531    }
532
533    pub fn repair_unit(
534        &self,
535        options: &[UnitCommandOptions],
536        command_id: Option<i32>,
537        timeout: Option<i32>,
538        target: Unit,
539    ) -> Result<(), &'static str> {
540        let mut command_data = RepairUnitCommandData {
541            unit_id: self.unit_id,
542            group_id: -1,
543            options: options.to_vec(),
544            timeout: timeout.unwrap_or(i32::MAX),
545            to_repair_unit_id: target.unit_id,
546        };
547
548        handle_command(
549            self.ai_id,
550            COMMAND_TO_ID_ENGINE,
551            command_id.unwrap_or(-1),
552            CommandTopic::UnitRepair.into(),
553            &mut command_data.c_data(),
554        )
555    }
556
557    pub fn restore_area(
558        &self,
559        options: &[UnitCommandOptions],
560        command_id: Option<i32>,
561        timeout: Option<i32>,
562        position: [f32; 3],
563        radius: f32,
564    ) -> Result<(), &'static str> {
565        let mut command_data = RestoreAreaUnitCommandData {
566            unit_id: self.unit_id,
567            group_id: -1,
568            options: options.to_vec(),
569            timeout: timeout.unwrap_or(i32::MAX),
570            position,
571            radius,
572        };
573
574        handle_command(
575            self.ai_id,
576            COMMAND_TO_ID_ENGINE,
577            command_id.unwrap_or(-1),
578            CommandTopic::UnitRestoreArea.into(),
579            &mut command_data.c_data(),
580        )
581    }
582
583    pub fn resurrect_unit(
584        &self,
585        options: &[UnitCommandOptions],
586        command_id: Option<i32>,
587        timeout: Option<i32>,
588        target: Unit,
589    ) -> Result<(), &'static str> {
590        let mut command_data = ResurrectUnitCommandData {
591            unit_id: self.unit_id,
592            group_id: -1,
593            options: options.to_vec(),
594            timeout: timeout.unwrap_or(i32::MAX),
595            to_resurrect_feature_id: target.unit_id,
596        };
597
598        handle_command(
599            self.ai_id,
600            COMMAND_TO_ID_ENGINE,
601            command_id.unwrap_or(-1),
602            CommandTopic::UnitResurrect.into(),
603            &mut command_data.c_data(),
604        )
605    }
606
607    pub fn resurrect_area(
608        &self,
609        options: &[UnitCommandOptions],
610        command_id: Option<i32>,
611        timeout: Option<i32>,
612        position: [f32; 3],
613        radius: f32,
614    ) -> Result<(), &'static str> {
615        let mut command_data = ResurrectAreaUnitCommandData {
616            unit_id: self.unit_id,
617            group_id: -1,
618            options: options.to_vec(),
619            timeout: timeout.unwrap_or(i32::MAX),
620            position,
621            radius,
622        };
623
624        handle_command(
625            self.ai_id,
626            COMMAND_TO_ID_ENGINE,
627            command_id.unwrap_or(-1),
628            CommandTopic::UnitResurrectArea.into(),
629            &mut command_data.c_data(),
630        )
631    }
632
633    pub fn self_destruct(
634        &self,
635        options: &[UnitCommandOptions],
636        command_id: Option<i32>,
637        timeout: Option<i32>,
638    ) -> Result<(), &'static str> {
639        let mut command_data = SelfDestroyUnitCommandData {
640            unit_id: self.unit_id,
641            group_id: -1,
642            options: options.to_vec(),
643            timeout: timeout.unwrap_or(i32::MAX),
644        };
645
646        handle_command(
647            self.ai_id,
648            COMMAND_TO_ID_ENGINE,
649            command_id.unwrap_or(-1),
650            CommandTopic::UnitSelfDestroy.into(),
651            &mut command_data.c_data(),
652        )
653    }
654
655    pub fn set_auto_repair_level(
656        &self,
657        options: &[UnitCommandOptions],
658        command_id: Option<i32>,
659        timeout: Option<i32>,
660        auto_repair_level: i32,
661    ) -> Result<(), &'static str> {
662        let mut command_data = SetAutoRepairLevelUnitCommandData {
663            unit_id: self.unit_id,
664            group_id: -1,
665            options: options.to_vec(),
666            timeout: timeout.unwrap_or(i32::MAX),
667            auto_repair_level,
668        };
669
670        handle_command(
671            self.ai_id,
672            COMMAND_TO_ID_ENGINE,
673            command_id.unwrap_or(-1),
674            CommandTopic::UnitSetAutoRepairLevel.into(),
675            &mut command_data.c_data(),
676        )
677    }
678
679    pub fn set_base_command(
680        &self,
681        options: &[UnitCommandOptions],
682        command_id: Option<i32>,
683        timeout: Option<i32>,
684        base_position: [f32; 3],
685    ) -> Result<(), &'static str> {
686        let mut command_data = SetBaseUnitCommandData {
687            unit_id: self.unit_id,
688            group_id: -1,
689            options: options.to_vec(),
690            timeout: timeout.unwrap_or(i32::MAX),
691            base_position,
692        };
693
694        handle_command(
695            self.ai_id,
696            COMMAND_TO_ID_ENGINE,
697            command_id.unwrap_or(-1),
698            CommandTopic::UnitSetBase.into(),
699            &mut command_data.c_data(),
700        )
701    }
702
703    pub fn set_fire_state(
704        &self,
705        options: &[UnitCommandOptions],
706        command_id: Option<i32>,
707        timeout: Option<i32>,
708        fire_state: FireState,
709    ) -> Result<(), &'static str> {
710        let mut command_data = SetFireUnitCommandData {
711            unit_id: self.unit_id,
712            group_id: -1,
713            options: options.to_vec(),
714            timeout: timeout.unwrap_or(i32::MAX),
715            fire_state,
716        };
717
718        handle_command(
719            self.ai_id,
720            COMMAND_TO_ID_ENGINE,
721            command_id.unwrap_or(-1),
722            CommandTopic::UnitSetFireState.into(),
723            &mut command_data.c_data(),
724        )
725    }
726
727    pub fn set_idle_mode(
728        &self,
729        options: &[UnitCommandOptions],
730        command_id: Option<i32>,
731        timeout: Option<i32>,
732        idle_mode: IdleMode,
733    ) -> Result<(), &'static str> {
734        let mut command_data = SetIdleModeCommandData {
735            unit_id: self.unit_id,
736            group_id: -1,
737            options: options.to_vec(),
738            timeout: timeout.unwrap_or(i32::MAX),
739            idle_mode,
740        };
741
742        handle_command(
743            self.ai_id,
744            COMMAND_TO_ID_ENGINE,
745            command_id.unwrap_or(-1),
746            CommandTopic::UnitSetIdleMode.into(),
747            &mut command_data.c_data(),
748        )
749    }
750
751    pub fn set_move_state(
752        &self,
753        options: &[UnitCommandOptions],
754        command_id: Option<i32>,
755        timeout: Option<i32>,
756        move_state: MoveState,
757    ) -> Result<(), &'static str> {
758        let mut command_data = SetMoveStateCommandData {
759            unit_id: self.unit_id,
760            group_id: -1,
761            options: options.to_vec(),
762            timeout: timeout.unwrap_or(i32::MAX),
763            move_state,
764        };
765
766        handle_command(
767            self.ai_id,
768            COMMAND_TO_ID_ENGINE,
769            command_id.unwrap_or(-1),
770            CommandTopic::UnitSetMoveState.into(),
771            &mut command_data.c_data(),
772        )
773    }
774
775    pub fn set_on_off(
776        &self,
777        options: &[UnitCommandOptions],
778        command_id: Option<i32>,
779        timeout: Option<i32>,
780        on: bool,
781    ) -> Result<(), &'static str> {
782        let mut command_data = SetUnitOnOffCommandData {
783            unit_id: self.unit_id,
784            group_id: -1,
785            options: options.to_vec(),
786            timeout: timeout.unwrap_or(i32::MAX),
787            on,
788        };
789
790        handle_command(
791            self.ai_id,
792            COMMAND_TO_ID_ENGINE,
793            command_id.unwrap_or(-1),
794            CommandTopic::UnitSetOnOff.into(),
795            &mut command_data.c_data(),
796        )
797    }
798
799    pub fn set_repeat(
800        &self,
801        options: &[UnitCommandOptions],
802        command_id: Option<i32>,
803        timeout: Option<i32>,
804        repeat: bool,
805    ) -> Result<(), &'static str> {
806        let mut command_data = SetUnitRepeatCommandData {
807            unit_id: self.unit_id,
808            group_id: -1,
809            options: options.to_vec(),
810            timeout: timeout.unwrap_or(i32::MAX),
811            repeat,
812        };
813
814        handle_command(
815            self.ai_id,
816            COMMAND_TO_ID_ENGINE,
817            command_id.unwrap_or(-1),
818            CommandTopic::UnitSetRepeat.into(),
819            &mut command_data.c_data(),
820        )
821    }
822
823    pub fn set_trajectory(
824        &self,
825        options: &[UnitCommandOptions],
826        command_id: Option<i32>,
827        timeout: Option<i32>,
828        trajectory: Trajectory,
829    ) -> Result<(), &'static str> {
830        let mut command_data = SetUnitTrajectoryCommandData {
831            unit_id: self.unit_id,
832            group_id: -1,
833            options: options.to_vec(),
834            timeout: timeout.unwrap_or(i32::MAX),
835            trajectory,
836        };
837
838        handle_command(
839            self.ai_id,
840            COMMAND_TO_ID_ENGINE,
841            command_id.unwrap_or(-1),
842            CommandTopic::UnitSetTrajectory.into(),
843            &mut command_data.c_data(),
844        )
845    }
846
847    pub fn stockpile(
848        &self,
849        options: &[UnitCommandOptions],
850        command_id: Option<i32>,
851        timeout: Option<i32>,
852    ) -> Result<(), &'static str> {
853        let mut command_data = SetUnitStockpileCommandData {
854            unit_id: self.unit_id,
855            group_id: -1,
856            options: options.to_vec(),
857            timeout: timeout.unwrap_or(i32::MAX),
858        };
859
860        handle_command(
861            self.ai_id,
862            COMMAND_TO_ID_ENGINE,
863            command_id.unwrap_or(-1),
864            CommandTopic::UnitStockpile.into(),
865            &mut command_data.c_data(),
866        )
867    }
868
869    pub fn stop(
870        &self,
871        options: &[UnitCommandOptions],
872        command_id: Option<i32>,
873        timeout: Option<i32>,
874    ) -> Result<(), &'static str> {
875        let mut command_data = SetUnitStopCommandData {
876            unit_id: self.unit_id,
877            group_id: -1,
878            options: options.to_vec(),
879            timeout: timeout.unwrap_or(i32::MAX),
880        };
881
882        handle_command(
883            self.ai_id,
884            COMMAND_TO_ID_ENGINE,
885            command_id.unwrap_or(-1),
886            CommandTopic::UnitStop.into(),
887            &mut command_data.c_data(),
888        )
889    }
890
891    pub fn unload(
892        &self,
893        options: &[UnitCommandOptions],
894        command_id: Option<i32>,
895        timeout: Option<i32>,
896        position: [f32; 3],
897        to_unload_unit: Unit,
898    ) -> Result<(), &'static str> {
899        let mut command_data = SetUnitUnloadCommandData {
900            unit_id: self.unit_id,
901            group_id: -1,
902            options: options.to_vec(),
903            timeout: timeout.unwrap_or(i32::MAX),
904            position,
905            to_unload_unit_id: to_unload_unit.unit_id,
906        };
907
908        handle_command(
909            self.ai_id,
910            COMMAND_TO_ID_ENGINE,
911            command_id.unwrap_or(-1),
912            CommandTopic::UnitUnloadUnit.into(),
913            &mut command_data.c_data(),
914        )
915    }
916
917    pub fn unload_area(
918        &self,
919        options: &[UnitCommandOptions],
920        command_id: Option<i32>,
921        timeout: Option<i32>,
922        position: [f32; 3],
923        radius: f32,
924    ) -> Result<(), &'static str> {
925        let mut command_data = SetUnitUnloadAreaCommandData {
926            unit_id: self.unit_id,
927            group_id: -1,
928            options: options.to_vec(),
929            timeout: timeout.unwrap_or(i32::MAX),
930            position,
931            radius,
932        };
933
934        handle_command(
935            self.ai_id,
936            COMMAND_TO_ID_ENGINE,
937            command_id.unwrap_or(-1),
938            CommandTopic::UnitUnloadUnitsArea.into(),
939            &mut command_data.c_data(),
940        )
941    }
942
943    pub fn wait(
944        &self,
945        options: &[UnitCommandOptions],
946        command_id: Option<i32>,
947        timeout: Option<i32>,
948    ) -> Result<(), &'static str> {
949        let mut command_data = SetUnitWaitCommandData {
950            unit_id: self.unit_id,
951            group_id: -1,
952            options: options.to_vec(),
953            timeout: timeout.unwrap_or(i32::MAX),
954        };
955
956        handle_command(
957            self.ai_id,
958            COMMAND_TO_ID_ENGINE,
959            command_id.unwrap_or(-1),
960            CommandTopic::UnitWait.into(),
961            &mut command_data.c_data(),
962        )
963    }
964
965    pub fn wait_death(
966        &self,
967        options: &[UnitCommandOptions],
968        command_id: Option<i32>,
969        timeout: Option<i32>,
970    ) -> Result<(), &'static str> {
971        let mut command_data = SetUnitWaitCommandData {
972            unit_id: self.unit_id,
973            group_id: -1,
974            options: options.to_vec(),
975            timeout: timeout.unwrap_or(i32::MAX),
976        };
977
978        handle_command(
979            self.ai_id,
980            COMMAND_TO_ID_ENGINE,
981            command_id.unwrap_or(-1),
982            CommandTopic::UnitWaitDeath.into(),
983            &mut command_data.c_data(),
984        )
985    }
986
987    pub fn wait_gather(
988        &self,
989        options: &[UnitCommandOptions],
990        command_id: Option<i32>,
991        timeout: Option<i32>,
992    ) -> Result<(), &'static str> {
993        let mut command_data = SetUnitWaitGatherCommandData {
994            unit_id: self.unit_id,
995            group_id: -1,
996            options: options.to_vec(),
997            timeout: timeout.unwrap_or(i32::MAX),
998        };
999
1000        handle_command(
1001            self.ai_id,
1002            COMMAND_TO_ID_ENGINE,
1003            command_id.unwrap_or(-1),
1004            CommandTopic::UnitWaitGather.into(),
1005            &mut command_data.c_data(),
1006        )
1007    }
1008
1009    pub fn wait_squad(
1010        &self,
1011        options: &[UnitCommandOptions],
1012        command_id: Option<i32>,
1013        timeout: Option<i32>,
1014        num_units: i32,
1015    ) -> Result<(), &'static str> {
1016        let mut command_data = SetUnitWaitSquadCommandData {
1017            unit_id: self.unit_id,
1018            group_id: -1,
1019            options: options.to_vec(),
1020            timeout: timeout.unwrap_or(i32::MAX),
1021            num_units,
1022        };
1023
1024        handle_command(
1025            self.ai_id,
1026            COMMAND_TO_ID_ENGINE,
1027            command_id.unwrap_or(-1),
1028            CommandTopic::UnitWaitSquad.into(),
1029            &mut command_data.c_data(),
1030        )
1031    }
1032
1033    pub fn wait_time(
1034        &self,
1035        options: &[UnitCommandOptions],
1036        command_id: Option<i32>,
1037        timeout: Option<i32>,
1038        time: i32,
1039    ) -> Result<(), &'static str> {
1040        let mut command_data = SetUnitWaitTimeCommandData {
1041            unit_id: self.unit_id,
1042            group_id: -1,
1043            options: options.to_vec(),
1044            timeout: timeout.unwrap_or(i32::MAX),
1045            time,
1046        };
1047
1048        handle_command(
1049            self.ai_id,
1050            COMMAND_TO_ID_ENGINE,
1051            command_id.unwrap_or(-1),
1052            CommandTopic::UnitWaitTime.into(),
1053            &mut command_data.c_data(),
1054        )
1055    }
1056}