screeps/objects/impls/
creep.rs

1use js_sys::{Array, JsString};
2use wasm_bindgen::prelude::*;
3
4use crate::{
5    constants::{Direction, Part, ResourceType},
6    enums::action_error_codes::{
7        AttackControllerErrorCode, BuildErrorCode, ClaimControllerErrorCode, CreepAttackErrorCode,
8        CreepCancelOrderErrorCode, CreepHealErrorCode, CreepMoveByPathErrorCode,
9        CreepMoveDirectionErrorCode, CreepMovePulledByErrorCode, CreepMoveToErrorCode,
10        CreepRepairErrorCode, DismantleErrorCode, DropErrorCode, GenerateSafeModeErrorCode,
11        HarvestErrorCode, NotifyWhenAttackedErrorCode, PickupErrorCode, PullErrorCode,
12        RangedAttackErrorCode, RangedHealErrorCode, RangedMassAttackErrorCode,
13        ReserveControllerErrorCode, SayErrorCode, SignControllerErrorCode, SuicideErrorCode,
14        TransferErrorCode, UpgradeControllerErrorCode, WithdrawErrorCode,
15    },
16    objects::{
17        ConstructionSite, Owner, Resource, RoomObject, Store, Structure, StructureController,
18    },
19    pathfinder::SingleRoomCostResult,
20    prelude::*,
21    CostMatrix, MoveToOptions, RoomName, RoomPosition,
22};
23
24#[cfg(feature = "seasonal-season-5")]
25use crate::objects::Reactor;
26
27#[cfg(feature = "seasonal-season-5")]
28use crate::enums::action_error_codes::CreepClaimReactorErrorCode;
29
30#[wasm_bindgen]
31extern "C" {
32    /// A [`Creep`] unit in the game world.
33    ///
34    /// [Screeps documentation](https://docs.screeps.com/api/#Creep)
35    #[wasm_bindgen(extends = RoomObject)]
36    #[derive(Clone, Debug)]
37    pub type Creep;
38
39    // explicitly structural getters here, as these may have varying
40    // getter methods (notably on the first tick a creep is spawning):
41    // https://github.com/screeps/engine/blob/c6c4fc9e656f160e0e0174b0dd9a817d2dd18976/src/game/structures.js#L1134-L1213
42    #[wasm_bindgen(structural, method, getter = body)]
43    fn body_internal(this: &Creep) -> Array;
44
45    #[wasm_bindgen(structural, method, getter = fatigue)]
46    fn fatigue_internal(this: &Creep) -> u32;
47
48    #[wasm_bindgen(structural, method, getter = hits)]
49    fn hits_internal(this: &Creep) -> u32;
50
51    #[wasm_bindgen(structural, method, getter = hitsMax)]
52    fn hits_max_internal(this: &Creep) -> u32;
53
54    #[wasm_bindgen(structural, method, getter = id)]
55    fn id_internal(this: &Creep) -> Option<JsString>;
56
57    #[wasm_bindgen(structural, method, getter = memory)]
58    fn memory_internal(this: &Creep) -> JsValue;
59
60    #[wasm_bindgen(structural, method, setter = memory)]
61    fn set_memory_internal(this: &Creep, val: &JsValue);
62
63    #[wasm_bindgen(structural, method, getter = my)]
64    fn my_internal(this: &Creep) -> bool;
65
66    #[wasm_bindgen(structural, method, getter = name)]
67    fn name_internal(this: &Creep) -> String;
68
69    #[wasm_bindgen(structural, method, getter = name)]
70    fn name_jsstring_internal(this: &Creep) -> JsString;
71
72    #[wasm_bindgen(structural, method, getter = owner)]
73    fn owner_internal(this: &Creep) -> Owner;
74
75    #[wasm_bindgen(structural, method, getter = saying)]
76    fn saying_internal(this: &Creep) -> Option<JsString>;
77
78    #[wasm_bindgen(structural, method, getter = spawning)]
79    fn spawning_internal(this: &Creep) -> bool;
80
81    #[wasm_bindgen(structural, method, getter = store)]
82    fn store_internal(this: &Creep) -> Store;
83
84    #[wasm_bindgen(structural, method, getter = ticksToLive)]
85    fn ticks_to_live_internal(this: &Creep) -> Option<u32>;
86
87    #[wasm_bindgen(final, method, js_name = attack)]
88    fn attack_internal(this: &Creep, target: &RoomObject) -> i8;
89
90    #[wasm_bindgen(final, method, js_name = attackController)]
91    fn attack_controller_internal(this: &Creep, target: &StructureController) -> i8;
92
93    #[wasm_bindgen(final, method, js_name = build)]
94    fn build_internal(this: &Creep, target: &ConstructionSite) -> i8;
95
96    #[wasm_bindgen(final, method, js_name = cancelOrder)]
97    fn cancel_order_internal(this: &Creep, target: &JsString) -> i8;
98
99    #[wasm_bindgen(final, method, js_name = claimController)]
100    fn claim_controller_internal(this: &Creep, target: &StructureController) -> i8;
101
102    #[cfg(feature = "seasonal-season-5")]
103    #[wasm_bindgen(final, method, js_name = claimReactor)]
104    fn claim_reactor_internal(this: &Creep, target: &Reactor) -> i8;
105
106    #[wasm_bindgen(final, method, js_name = dismantle)]
107    fn dismantle_internal(this: &Creep, target: &Structure) -> i8;
108
109    #[wasm_bindgen(final, method, js_name = drop)]
110    fn drop_internal(this: &Creep, ty: ResourceType, amount: Option<u32>) -> i8;
111
112    #[wasm_bindgen(final, method, js_name = generateSafeMode)]
113    fn generate_safe_mode_internal(this: &Creep, target: &StructureController) -> i8;
114
115    #[wasm_bindgen(final, method, js_name = getActiveBodyparts)]
116    fn get_active_bodyparts_internal(this: &Creep, ty: Part) -> u8;
117
118    #[wasm_bindgen(final, method, js_name = harvest)]
119    fn harvest_internal(this: &Creep, target: &RoomObject) -> i8;
120
121    #[wasm_bindgen(final, method, js_name = heal)]
122    fn heal_internal(this: &Creep, target: &RoomObject) -> i8;
123
124    #[wasm_bindgen(final, method, js_name = move)]
125    fn move_direction_internal(this: &Creep, direction: Direction) -> i8;
126
127    #[wasm_bindgen(final, method, js_name = move)]
128    fn move_pulled_by_internal(this: &Creep, target: &Creep) -> i8;
129
130    #[wasm_bindgen(final, method, js_name = moveByPath)]
131    fn move_by_path_internal(this: &Creep, path: &JsValue) -> i8;
132
133    #[wasm_bindgen(final, method, js_name = moveTo)]
134    fn move_to_internal(this: &Creep, target: &JsValue, options: &JsValue) -> i8;
135
136    #[wasm_bindgen(final, method, js_name = notifyWhenAttacked)]
137    fn notify_when_attacked_internal(this: &Creep, enabled: bool) -> i8;
138
139    #[wasm_bindgen(final, method, js_name = pickup)]
140    fn pickup_internal(this: &Creep, target: &Resource) -> i8;
141
142    #[wasm_bindgen(final, method, js_name = pull)]
143    fn pull_internal(this: &Creep, target: &Creep) -> i8;
144
145    #[wasm_bindgen(final, method, js_name = rangedAttack)]
146    fn ranged_attack_internal(this: &Creep, target: &RoomObject) -> i8;
147
148    #[wasm_bindgen(final, method, js_name = rangedHeal)]
149    fn ranged_heal_internal(this: &Creep, target: &RoomObject) -> i8;
150
151    #[wasm_bindgen(final, method, js_name = rangedMassAttack)]
152    fn ranged_mass_attack_internal(this: &Creep) -> i8;
153
154    #[wasm_bindgen(final, method, js_name = repair)]
155    fn repair_internal(this: &Creep, target: &RoomObject) -> i8;
156
157    #[wasm_bindgen(final, method, js_name = reserveController)]
158    fn reserve_controller_internal(this: &Creep, target: &StructureController) -> i8;
159
160    #[wasm_bindgen(final, method, js_name = say)]
161    fn say_internal(this: &Creep, message: &str, public: bool) -> i8;
162
163    #[wasm_bindgen(final, method, js_name = signController)]
164    fn sign_controller_internal(this: &Creep, target: &StructureController, text: &str) -> i8;
165
166    #[wasm_bindgen(final, method, js_name = suicide)]
167    fn suicide_internal(this: &Creep) -> i8;
168
169    #[wasm_bindgen(final, method, js_name = transfer)]
170    fn transfer_internal(
171        this: &Creep,
172        target: &RoomObject,
173        ty: ResourceType,
174        amount: Option<u32>,
175    ) -> i8;
176
177    #[wasm_bindgen(final, method, js_name = upgradeController)]
178    fn upgrade_controller_internal(this: &Creep, target: &StructureController) -> i8;
179
180    #[wasm_bindgen(final, method, js_name = withdraw)]
181    fn withdraw_internal(
182        this: &Creep,
183        target: &RoomObject,
184        ty: ResourceType,
185        amount: Option<u32>,
186    ) -> i8;
187}
188
189impl Creep {
190    /// Retrieve a [`Vec<BodyPart>`] containing details about the creep's body
191    /// parts and boosts.
192    ///
193    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.body)
194    pub fn body(&self) -> Vec<BodyPart> {
195        self.body_internal().iter().map(BodyPart::from).collect()
196    }
197
198    /// The amount of fatigue the creep has. If greater than 0, it cannot move
199    /// this tick without being pulled.
200    ///
201    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.fatigue)
202    pub fn fatigue(&self) -> u32 {
203        self.fatigue_internal()
204    }
205
206    /// Retrieve the current hits of this creep.
207    ///
208    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.hits)
209    pub fn hits(&self) -> u32 {
210        self.hits_internal()
211    }
212
213    /// Retrieve the maximum hits of this creep, which generally equals 50 per
214    /// body part.
215    ///
216    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.hitsMax)
217    pub fn hits_max(&self) -> u32 {
218        self.hits_max_internal()
219    }
220
221    /// A shortcut to `Memory.creeps[creep.name]`.
222    ///
223    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.memory)
224    pub fn memory(&self) -> JsValue {
225        self.memory_internal()
226    }
227
228    /// Sets a new value to `Memory.creeps[creep.name]`.
229    ///
230    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.memory)
231    pub fn set_memory(&self, val: &JsValue) {
232        self.set_memory_internal(val)
233    }
234
235    /// Whether this creep is owned by the player.
236    ///
237    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.my)
238    pub fn my(&self) -> bool {
239        self.my_internal()
240    }
241
242    /// The [`Owner`] of this creep that contains the owner's username.
243    ///
244    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.owner)
245    pub fn owner(&self) -> Owner {
246        self.owner_internal()
247    }
248
249    /// What the creep said last tick.
250    ///
251    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.saying)
252    pub fn saying(&self) -> Option<JsString> {
253        self.saying_internal()
254    }
255
256    /// Whether the creep is still spawning.
257    ///
258    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.spawning)
259    pub fn spawning(&self) -> bool {
260        self.spawning_internal()
261    }
262
263    /// The [`Store`] of the creep, which contains information about what
264    /// resources it is it carrying.
265    ///
266    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.store)
267    pub fn store(&self) -> Store {
268        self.store_internal()
269    }
270
271    /// The number of ticks the creep has left to live
272    ///
273    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.ticksToLive)
274    pub fn ticks_to_live(&self) -> Option<u32> {
275        self.ticks_to_live_internal()
276    }
277
278    /// Attack a target in melee range using a creep's attack parts.
279    ///
280    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.attack)
281    pub fn attack<T>(&self, target: &T) -> Result<(), CreepAttackErrorCode>
282    where
283        T: ?Sized + Attackable,
284    {
285        CreepAttackErrorCode::result_from_i8(self.attack_internal(target.as_ref()))
286    }
287
288    /// Attack a [`StructureController`] in melee range using a creep's claim
289    /// parts.
290    ///
291    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.attackController)
292    pub fn attack_controller(
293        &self,
294        target: &StructureController,
295    ) -> Result<(), AttackControllerErrorCode> {
296        AttackControllerErrorCode::result_from_i8(self.attack_controller_internal(target))
297    }
298
299    /// Use a creep's work parts to consume carried energy, putting it toward
300    /// progress in a [`ConstructionSite`] in range 3.
301    ///
302    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.build)
303    pub fn build(&self, target: &ConstructionSite) -> Result<(), BuildErrorCode> {
304        BuildErrorCode::result_from_i8(self.build_internal(target))
305    }
306
307    /// Cancel a successfully called creep function from earlier in the tick,
308    /// with a [`JsString`] that must contain the JS version of the function
309    /// name.
310    ///
311    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.cancelOrder)
312    pub fn cancel_order(&self, target: &JsString) -> Result<(), CreepCancelOrderErrorCode> {
313        CreepCancelOrderErrorCode::result_from_i8(self.cancel_order_internal(target))
314    }
315
316    /// Claim an unowned [`StructureController`] in melee range as your own
317    /// using a creep's claim parts.
318    ///
319    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.claimController)
320    pub fn claim_controller(
321        &self,
322        target: &StructureController,
323    ) -> Result<(), ClaimControllerErrorCode> {
324        ClaimControllerErrorCode::result_from_i8(self.claim_controller_internal(target))
325    }
326
327    /// Claim a [`Reactor`] in melee range as your own using a creep's claim
328    /// parts.
329    ///
330    /// [Screeps documentation](https://docs-season.screeps.com/api/#Creep.claimReactor)
331    #[cfg(feature = "seasonal-season-5")]
332    pub fn claim_reactor(&self, target: &Reactor) -> Result<(), CreepClaimReactorErrorCode> {
333        CreepClaimReactorErrorCode::result_from_i8(self.claim_reactor_internal(target))
334    }
335
336    /// Dismantle a [`Structure`] in melee range, removing [`DISMANTLE_POWER`]
337    /// hits per effective work part, giving the creep energy equivalent to half
338    /// of the cost to repair the same hits. Can only be used against types
339    /// of structures that can be constructed; if
340    /// [`StructureType::construction_cost`] is `None`, dismantling is
341    /// impossible.
342    ///
343    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.dismantle)
344    ///
345    /// [`DISMANTLE_POWER`]: crate::constants::DISMANTLE_POWER
346    /// [`StructureType::construction_cost`]: crate::constants::StructureType::construction_cost
347    pub fn dismantle<T>(&self, target: &T) -> Result<(), DismantleErrorCode>
348    where
349        T: ?Sized + Dismantleable,
350    {
351        DismantleErrorCode::result_from_i8(self.dismantle_internal(target.as_ref()))
352    }
353
354    /// Drop a resource on the ground from the creep's [`Store`].
355    ///
356    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.drop)
357    pub fn drop(&self, ty: ResourceType, amount: Option<u32>) -> Result<(), DropErrorCode> {
358        DropErrorCode::result_from_i8(self.drop_internal(ty, amount))
359    }
360
361    /// Consume [`ResourceType::Ghodium`] (in the amount of [`SAFE_MODE_COST`])
362    /// from the creep's [`Store`] to add a safe mode activation to a
363    /// [`StructureController`] in melee range.
364    ///
365    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.generateSafeMode)
366    ///
367    /// [`SAFE_MODE_COST`]: crate::constants::SAFE_MODE_COST
368    pub fn generate_safe_mode(
369        &self,
370        target: &StructureController,
371    ) -> Result<(), GenerateSafeModeErrorCode> {
372        GenerateSafeModeErrorCode::result_from_i8(self.generate_safe_mode_internal(target))
373    }
374
375    /// Get the number of parts of the given type the creep has in its body,
376    /// excluding fully damaged parts.
377    ///
378    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.getActiveBodyparts)
379    pub fn get_active_bodyparts(&self, ty: Part) -> u8 {
380        self.get_active_bodyparts_internal(ty)
381    }
382
383    /// Harvest from a [`Source`], [`Mineral`], or [`Deposit`] in melee range.
384    ///
385    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.harvest)
386    ///
387    /// [`Source`]: crate::objects::Source
388    /// [`Mineral`]: crate::objects::Mineral
389    /// [`Deposit`]: crate::objects::Deposit
390    pub fn harvest<T>(&self, target: &T) -> Result<(), HarvestErrorCode>
391    where
392        T: ?Sized + Harvestable,
393    {
394        HarvestErrorCode::result_from_i8(self.harvest_internal(target.as_ref()))
395    }
396
397    /// Heal a [`Creep`] or [`PowerCreep`] in melee range, including itself.
398    ///
399    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.heal)
400    ///
401    /// [`PowerCreep`]: crate::objects::PowerCreep
402    pub fn heal<T>(&self, target: &T) -> Result<(), CreepHealErrorCode>
403    where
404        T: ?Sized + Healable,
405    {
406        CreepHealErrorCode::result_from_i8(self.heal_internal(target.as_ref()))
407    }
408
409    /// Move one square in the specified direction.
410    ///
411    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.move)
412    pub fn move_direction(&self, direction: Direction) -> Result<(), CreepMoveDirectionErrorCode> {
413        CreepMoveDirectionErrorCode::result_from_i8(self.move_direction_internal(direction))
414    }
415
416    /// Accept an attempt by another creep to pull this one.
417    ///
418    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.move)
419    pub fn move_pulled_by(&self, target: &Creep) -> Result<(), CreepMovePulledByErrorCode> {
420        CreepMovePulledByErrorCode::result_from_i8(self.move_pulled_by_internal(target))
421    }
422
423    /// Move the creep along a previously determined path returned from a
424    /// pathfinding function, in array or serialized string form.
425    ///
426    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.moveByPath)
427    pub fn move_by_path(&self, path: &JsValue) -> Result<(), CreepMoveByPathErrorCode> {
428        CreepMoveByPathErrorCode::result_from_i8(self.move_by_path_internal(path))
429    }
430
431    /// Whether to send an email notification when this creep is attacked.
432    ///
433    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.notifyWhenAttacked)
434    pub fn notify_when_attacked(&self, enabled: bool) -> Result<(), NotifyWhenAttackedErrorCode> {
435        NotifyWhenAttackedErrorCode::result_from_i8(self.notify_when_attacked_internal(enabled))
436    }
437
438    /// Pick up a [`Resource`] in melee range (or at the same position as the
439    /// creep).
440    ///
441    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.pickup)
442    pub fn pickup(&self, target: &Resource) -> Result<(), PickupErrorCode> {
443        PickupErrorCode::result_from_i8(self.pickup_internal(target))
444    }
445
446    /// Help another creep to move by pulling, if the second creep accepts.
447    ///
448    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.pull)
449    pub fn pull(&self, target: &Creep) -> Result<(), PullErrorCode> {
450        PullErrorCode::result_from_i8(self.pull_internal(target))
451    }
452
453    /// Attack a target in range 3 using a creep's ranged attack parts.
454    ///
455    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.rangedAttack)
456    pub fn ranged_attack<T>(&self, target: &T) -> Result<(), RangedAttackErrorCode>
457    where
458        T: ?Sized + Attackable,
459    {
460        RangedAttackErrorCode::result_from_i8(self.ranged_attack_internal(target.as_ref()))
461    }
462
463    /// Heal a target in range 3 using a creep's heal parts.
464    ///
465    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.rangedHeal)
466    pub fn ranged_heal<T>(&self, target: &T) -> Result<(), RangedHealErrorCode>
467    where
468        T: ?Sized + Healable,
469    {
470        RangedHealErrorCode::result_from_i8(self.ranged_heal_internal(target.as_ref()))
471    }
472
473    /// Attack all enemy targets in range using a creep's ranged attack parts,
474    /// with lower damage depending on range.
475    ///
476    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.rangedMassAttack)
477    pub fn ranged_mass_attack(&self) -> Result<(), RangedMassAttackErrorCode> {
478        RangedMassAttackErrorCode::result_from_i8(self.ranged_mass_attack_internal())
479    }
480
481    /// Repair a target in range 3 using carried energy and the creep's work
482    /// parts.
483    ///
484    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.repair)
485    pub fn repair<T>(&self, target: &T) -> Result<(), CreepRepairErrorCode>
486    where
487        T: ?Sized + Repairable,
488    {
489        CreepRepairErrorCode::result_from_i8(self.repair_internal(target.as_ref()))
490    }
491
492    /// Reserve an unowned [`StructureController`] in melee range using a
493    /// creep's claim parts.
494    ///
495    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.reserveController)
496    pub fn reserve_controller(
497        &self,
498        target: &StructureController,
499    ) -> Result<(), ReserveControllerErrorCode> {
500        ReserveControllerErrorCode::result_from_i8(self.reserve_controller_internal(target))
501    }
502
503    /// Display a string in a bubble above the creep next tick. 10 character
504    /// limit.
505    ///
506    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.say)
507    pub fn say(&self, message: &str, public: bool) -> Result<(), SayErrorCode> {
508        SayErrorCode::result_from_i8(self.say_internal(message, public))
509    }
510
511    /// Add (or remove, using an empty string) a sign to a
512    /// [`StructureController`] in melee range.
513    ///
514    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.signController)
515    pub fn sign_controller(
516        &self,
517        target: &StructureController,
518        text: &str,
519    ) -> Result<(), SignControllerErrorCode> {
520        SignControllerErrorCode::result_from_i8(self.sign_controller_internal(target, text))
521    }
522
523    /// Immediately kill the creep.
524    ///
525    /// Actions taken by the creep earlier in the tick may be cancelled.
526    ///
527    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.suicide)
528    pub fn suicide(&self) -> Result<(), SuicideErrorCode> {
529        SuicideErrorCode::result_from_i8(self.suicide_internal())
530    }
531
532    /// Upgrade a [`StructureController`] in range 3 using carried energy and
533    /// the creep's work parts.
534    ///
535    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.upgradeController)
536    pub fn upgrade_controller(
537        &self,
538        target: &StructureController,
539    ) -> Result<(), UpgradeControllerErrorCode> {
540        UpgradeControllerErrorCode::result_from_i8(self.upgrade_controller_internal(target))
541    }
542
543    /// Move the creep toward the specified goal, either a [`RoomPosition`] or
544    /// [`RoomObject`]. Note that using this function will store data in
545    /// `Memory.creeps[creep_name]` and enable the default serialization
546    /// behavior of the `Memory` object, which may hamper attempts to directly
547    /// use `RawMemory`.
548    ///
549    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.moveTo)
550    pub fn move_to<T>(&self, target: T) -> Result<(), CreepMoveToErrorCode>
551    where
552        T: HasPosition,
553    {
554        let target: RoomPosition = target.pos().into();
555        CreepMoveToErrorCode::result_from_i8(self.move_to_internal(&target, &JsValue::UNDEFINED))
556    }
557
558    /// Move the creep toward the specified goal, either a [`RoomPosition`] or
559    /// [`RoomObject`]. Note that using this function will store data in
560    /// `Memory.creeps[creep_name]` and enable the default serialization
561    /// behavior of the `Memory` object, which may hamper attempts to directly
562    /// use `RawMemory`.
563    ///
564    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.moveTo)
565    pub fn move_to_with_options<T, F>(
566        &self,
567        target: T,
568        options: Option<MoveToOptions<F>>,
569    ) -> Result<(), CreepMoveToErrorCode>
570    where
571        T: HasPosition,
572        F: FnMut(RoomName, CostMatrix) -> SingleRoomCostResult,
573    {
574        let target: RoomPosition = target.pos().into();
575
576        if let Some(options) = options {
577            options.into_js_options(|js_options| {
578                CreepMoveToErrorCode::result_from_i8(self.move_to_internal(&target, js_options))
579            })
580        } else {
581            CreepMoveToErrorCode::result_from_i8(
582                self.move_to_internal(&target, &JsValue::UNDEFINED),
583            )
584        }
585    }
586}
587
588impl JsCollectionFromValue for Creep {
589    fn from_value(val: JsValue) -> Self {
590        val.unchecked_into()
591    }
592}
593
594impl HasHits for Creep {
595    fn hits(&self) -> u32 {
596        self.hits()
597    }
598
599    fn hits_max(&self) -> u32 {
600        self.hits_max()
601    }
602}
603
604impl MaybeHasId for Creep {
605    /// The Object ID of the [`Creep`], or `None` if it began spawning this
606    /// tick.
607    ///
608    /// [Screeps documentation](https://docs.screeps.com/api/#Creep.id)
609    fn try_js_raw_id(&self) -> Option<JsString> {
610        self.id_internal()
611    }
612}
613
614impl HasStore for Creep {
615    fn store(&self) -> Store {
616        self.store()
617    }
618}
619
620impl Attackable for Creep {}
621impl Healable for Creep {}
622impl Transferable for Creep {}
623
624impl SharedCreepProperties for Creep {
625    fn memory(&self) -> JsValue {
626        self.memory()
627    }
628
629    fn set_memory(&self, val: &JsValue) {
630        self.set_memory(val)
631    }
632
633    fn my(&self) -> bool {
634        self.my()
635    }
636
637    fn name(&self) -> String {
638        self.name_internal()
639    }
640
641    fn name_jsstring(&self) -> JsString {
642        self.name_jsstring_internal()
643    }
644
645    fn owner(&self) -> Owner {
646        self.owner()
647    }
648
649    fn saying(&self) -> Option<JsString> {
650        self.saying()
651    }
652
653    fn ticks_to_live(&self) -> Option<u32> {
654        self.ticks_to_live()
655    }
656
657    fn drop(&self, ty: ResourceType, amount: Option<u32>) -> Result<(), DropErrorCode> {
658        self.drop(ty, amount)
659    }
660
661    fn notify_when_attacked(&self, enabled: bool) -> Result<(), NotifyWhenAttackedErrorCode> {
662        self.notify_when_attacked(enabled)
663    }
664
665    fn pickup(&self, target: &Resource) -> Result<(), PickupErrorCode> {
666        self.pickup(target)
667    }
668
669    fn say(&self, message: &str, public: bool) -> Result<(), SayErrorCode> {
670        self.say(message, public)
671    }
672
673    fn suicide(&self) -> Result<(), SuicideErrorCode> {
674        self.suicide()
675    }
676
677    fn transfer<T>(
678        &self,
679        target: &T,
680        ty: ResourceType,
681        amount: Option<u32>,
682    ) -> Result<(), TransferErrorCode>
683    where
684        T: Transferable + ?Sized,
685    {
686        TransferErrorCode::result_from_i8(self.transfer_internal(target.as_ref(), ty, amount))
687    }
688
689    fn withdraw<T>(
690        &self,
691        target: &T,
692        ty: ResourceType,
693        amount: Option<u32>,
694    ) -> Result<(), WithdrawErrorCode>
695    where
696        T: Withdrawable + ?Sized,
697    {
698        WithdrawErrorCode::result_from_i8(self.withdraw_internal(target.as_ref(), ty, amount))
699    }
700}
701
702#[wasm_bindgen]
703extern "C" {
704    /// A [`BodyPart`] of a creep.
705    ///
706    /// [Screeps documentation](https://docs-ptr.screeps.com/api/#Creep.body)
707    #[wasm_bindgen]
708    pub type BodyPart;
709
710    #[wasm_bindgen(method, getter)]
711    pub fn boost(this: &BodyPart) -> Option<ResourceType>;
712
713    #[wasm_bindgen(method, getter = type)]
714    pub fn part(this: &BodyPart) -> Part;
715
716    #[wasm_bindgen(method, getter)]
717    pub fn hits(this: &BodyPart) -> u32;
718}