screeps/objects/impls/
power_creep.rs

1use std::{error::Error, fmt};
2
3use js_sys::{JsString, Object};
4use wasm_bindgen::prelude::*;
5
6use crate::{
7    constants::{Direction, PowerCreepClass, PowerType, ResourceType},
8    enums::action_error_codes::{
9        DeleteErrorCode, DropErrorCode, EnableRoomErrorCode, NotifyWhenAttackedErrorCode,
10        PickupErrorCode, PowerCreepCancelOrderErrorCode, PowerCreepCreateErrorCode,
11        PowerCreepMoveByPathErrorCode, PowerCreepMoveDirectionErrorCode, PowerCreepMoveToErrorCode,
12        RenameErrorCode, RenewErrorCode, SayErrorCode, SpawnErrorCode, SuicideErrorCode,
13        TransferErrorCode, UpgradeErrorCode, UsePowerErrorCode, WithdrawErrorCode,
14    },
15    local::RoomName,
16    objects::{
17        CostMatrix, MoveToOptions, Owner, Resource, RoomObject, RoomPosition, Store,
18        StructureController, StructurePowerSpawn,
19    },
20    pathfinder::SingleRoomCostResult,
21    prelude::*,
22};
23
24#[wasm_bindgen]
25extern "C" {
26    /// A [`PowerCreep`] unit in the game world.
27    ///
28    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep)
29    #[wasm_bindgen(extends = RoomObject)]
30    #[derive(Clone, Debug)]
31    pub type PowerCreep;
32
33    #[wasm_bindgen(static_method_of = PowerCreep)]
34    fn create_internal(name: &JsString, class: PowerCreepClass) -> i8;
35
36    #[wasm_bindgen(method, getter = className)]
37    fn class_internal(this: &PowerCreep) -> PowerCreepClass;
38
39    #[wasm_bindgen(method, getter = hits)]
40    fn hits_internal(this: &PowerCreep) -> u32;
41
42    #[wasm_bindgen(method, getter = hitsMax)]
43    fn hits_max_internal(this: &PowerCreep) -> u32;
44
45    #[wasm_bindgen(method, getter = id)]
46    fn id_internal(this: &PowerCreep) -> JsString;
47
48    #[wasm_bindgen(method, getter = level)]
49    fn level_internal(this: &PowerCreep) -> u32;
50
51    #[wasm_bindgen(method, getter = memory)]
52    fn memory_internal(this: &PowerCreep) -> JsValue;
53
54    #[wasm_bindgen(method, setter = memory)]
55    fn set_memory_internal(this: &PowerCreep, val: &JsValue);
56
57    #[wasm_bindgen(method, getter = my)]
58    fn my_internal(this: &PowerCreep) -> bool;
59
60    #[wasm_bindgen(method, getter = name)]
61    fn name_internal(this: &PowerCreep) -> String;
62
63    #[wasm_bindgen(method, getter = name)]
64    fn name_jsstring_internal(this: &PowerCreep) -> JsString;
65
66    #[wasm_bindgen(method, getter = owner)]
67    fn owner_internal(this: &PowerCreep) -> Owner;
68
69    #[wasm_bindgen(method, getter = powers)]
70    fn powers_internal(this: &PowerCreep) -> Object;
71
72    #[wasm_bindgen(method, getter = saying)]
73    fn saying_internal(this: &PowerCreep) -> Option<JsString>;
74
75    #[wasm_bindgen(method, getter = store)]
76    fn store_internal(this: &PowerCreep) -> Store;
77
78    #[wasm_bindgen(method, getter = shard)]
79    fn shard_internal(this: &PowerCreep) -> Option<JsString>;
80
81    #[wasm_bindgen(method, getter = ticksToLive)]
82    fn ticks_to_live_internal(this: &PowerCreep) -> Option<u32>;
83
84    #[wasm_bindgen(method, js_name = cancelOrder)]
85    fn cancel_order_internal(this: &PowerCreep, target: &JsString) -> i8;
86
87    #[wasm_bindgen(method, js_name = drop)]
88    fn drop_internal(this: &PowerCreep, ty: ResourceType, amount: Option<u32>) -> i8;
89
90    #[wasm_bindgen(method, js_name = enableRoom)]
91    fn enable_room_internal(this: &PowerCreep, target: &StructureController) -> i8;
92
93    #[wasm_bindgen(method, js_name = move)]
94    fn move_direction_internal(this: &PowerCreep, direction: Direction) -> i8;
95
96    #[wasm_bindgen(method, js_name = moveByPath)]
97    fn move_by_path_internal(this: &PowerCreep, path: &JsValue) -> i8;
98
99    #[wasm_bindgen(method, js_name = moveTo)]
100    fn move_to_internal(this: &PowerCreep, target: &JsValue, options: &JsValue) -> i8;
101
102    #[wasm_bindgen(method, js_name = notifyWhenAttacked)]
103    fn notify_when_attacked_internal(this: &PowerCreep, enabled: bool) -> i8;
104
105    #[wasm_bindgen(method, js_name = pickup)]
106    fn pickup_internal(this: &PowerCreep, target: &Resource) -> i8;
107
108    #[wasm_bindgen(method, js_name = renew)]
109    fn renew_internal(this: &PowerCreep, target: &RoomObject) -> i8;
110
111    #[wasm_bindgen(method, js_name = say)]
112    fn say_internal(this: &PowerCreep, message: &str, public: bool) -> i8;
113
114    #[wasm_bindgen(method, js_name = suicide)]
115    fn suicide_internal(this: &PowerCreep) -> i8;
116
117    #[wasm_bindgen(method, js_name = transfer)]
118    fn transfer_internal(
119        this: &PowerCreep,
120        target: &RoomObject,
121        ty: ResourceType,
122        amount: Option<u32>,
123    ) -> i8;
124
125    #[wasm_bindgen(method, js_name = usePower)]
126    fn use_power_internal(this: &PowerCreep, power: PowerType, target: Option<&RoomObject>) -> i8;
127
128    #[wasm_bindgen(method, js_name = withdraw)]
129    fn withdraw_internal(
130        this: &PowerCreep,
131        target: &RoomObject,
132        ty: ResourceType,
133        amount: Option<u32>,
134    ) -> i8;
135}
136
137impl PowerCreep {
138    /// Create a new power creep in your account. Note that it will not
139    /// initially be spawned.
140    ///
141    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.create)
142    pub fn create(
143        name: &JsString,
144        class: PowerCreepClass,
145    ) -> Result<(), PowerCreepCreateErrorCode> {
146        PowerCreepCreateErrorCode::result_from_i8(Self::create_internal(name, class))
147    }
148
149    /// Retrieve this power creep's [`PowerCreepClass`].
150    ///
151    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.className)
152    pub fn class(&self) -> PowerCreepClass {
153        self.class_internal()
154    }
155
156    /// Retrieve the current hits of this power creep.
157    ///
158    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.hits)
159    pub fn hits(&self) -> u32 {
160        self.hits_internal()
161    }
162
163    /// Retrieve the maximum hits of this power creep.
164    ///
165    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.hitsMax)
166    pub fn hits_max(&self) -> u32 {
167        self.hits_max_internal()
168    }
169
170    /// Current level of the power creep, which can be increased with
171    /// [`AccountPowerCreep::upgrade`] if you have unspent GPL.
172    ///
173    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.level)
174    pub fn level(&self) -> u32 {
175        self.level_internal()
176    }
177
178    /// A shortcut to `Memory.powerCreeps[power_creep.name]`.
179    ///
180    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.memory)
181    pub fn memory(&self) -> JsValue {
182        self.memory_internal()
183    }
184
185    /// Sets a new value to `Memory.powerCreeps[power_creep.name]`.
186    ///
187    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.memory)
188    pub fn set_memory(&self, val: &JsValue) {
189        self.set_memory_internal(val)
190    }
191
192    /// Whether this power creep is owned by the player.
193    ///
194    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.my)
195    pub fn my(&self) -> bool {
196        self.my_internal()
197    }
198
199    /// The [`Owner`] of this power creep that contains the owner's username.
200    ///
201    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.owner)
202    pub fn owner(&self) -> Owner {
203        self.owner_internal()
204    }
205
206    /// The levels of this power creep's abilities, with [`PowerType`] keys and
207    /// values containing power level and cooldown.
208    ///
209    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.powers)
210    pub fn powers(&self) -> JsHashMap<PowerType, PowerInfo> {
211        self.powers_internal().into()
212    }
213
214    /// What the power creep said last tick.
215    ///
216    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.saying)
217    pub fn saying(&self) -> Option<JsString> {
218        self.saying_internal()
219    }
220
221    /// The [`Store`] of the power creep, which contains information about what
222    /// resources it is it carrying.
223    ///
224    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.store)
225    pub fn store(&self) -> Store {
226        self.store_internal()
227    }
228
229    /// The shard the power creep is currently spawned on, if spawned.
230    ///
231    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.shard)
232    pub fn shard(&self) -> Option<JsString> {
233        self.shard_internal()
234    }
235
236    /// The number of ticks the power creep has left to live, which can be
237    /// renewed at a [`StructurePowerSpawn`] or [`StructurePowerBank`]
238    ///
239    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.ticksToLive)
240    ///
241    /// [`StructurePowerBank`]: crate::objects::StructurePowerBank
242    pub fn ticks_to_live(&self) -> Option<u32> {
243        self.ticks_to_live_internal()
244    }
245
246    /// Cancel an a successfully called power creep function from earlier in the
247    /// tick, with a [`JsString`] that must contain the JS version of the
248    /// function name.
249    ///
250    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.cancelOrder)
251    pub fn cancel_order(&self, target: &JsString) -> Result<(), PowerCreepCancelOrderErrorCode> {
252        PowerCreepCancelOrderErrorCode::result_from_i8(self.cancel_order_internal(target))
253    }
254
255    /// Drop a resource on the ground from the power creep's [`Store`].
256    ///
257    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.drop)
258    pub fn drop(&self, ty: ResourceType, amount: Option<u32>) -> Result<(), DropErrorCode> {
259        DropErrorCode::result_from_i8(self.drop_internal(ty, amount))
260    }
261
262    /// Enable powers to be used in this room on a [`StructureController`] in
263    /// melee range. You do not need to own the controller.
264    ///
265    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.enableRoom)
266    pub fn enable_room(&self, target: &StructureController) -> Result<(), EnableRoomErrorCode> {
267        EnableRoomErrorCode::result_from_i8(self.enable_room_internal(target))
268    }
269
270    /// Move one square in the specified direction.
271    ///
272    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.move)
273    pub fn move_direction(
274        &self,
275        direction: Direction,
276    ) -> Result<(), PowerCreepMoveDirectionErrorCode> {
277        PowerCreepMoveDirectionErrorCode::result_from_i8(self.move_direction_internal(direction))
278    }
279
280    /// Move the power creep along a previously determined path returned from a
281    /// pathfinding function, in array or serialized string form.
282    ///
283    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.moveByPath)
284    pub fn move_by_path(&self, path: &JsValue) -> Result<(), PowerCreepMoveByPathErrorCode> {
285        PowerCreepMoveByPathErrorCode::result_from_i8(self.move_by_path_internal(path))
286    }
287
288    /// Whether to send an email notification when this power creep is attacked.
289    ///
290    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.notifyWhenAttacked)
291    pub fn notify_when_attacked(&self, enabled: bool) -> Result<(), NotifyWhenAttackedErrorCode> {
292        NotifyWhenAttackedErrorCode::result_from_i8(self.notify_when_attacked_internal(enabled))
293    }
294
295    /// Pick up a [`Resource`] in melee range (or at the same position as the
296    /// creep).
297    ///
298    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.pickup)
299    pub fn pickup(&self, target: &Resource) -> Result<(), PickupErrorCode> {
300        PickupErrorCode::result_from_i8(self.pickup_internal(target))
301    }
302
303    /// Renew the power creep's TTL using a [`StructurePowerSpawn`] or
304    /// [`StructurePowerBank`] in melee range.
305    ///
306    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.renew)
307    ///
308    /// [`StructurePowerBank`]: crate::objects::StructurePowerBank
309    pub fn renew(&self, target: &RoomObject) -> Result<(), RenewErrorCode> {
310        RenewErrorCode::result_from_i8(self.renew_internal(target))
311    }
312
313    /// Display a string in a bubble above the power creep next tick. 10
314    /// character limit.
315    ///
316    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.say)
317    pub fn say(&self, message: &str, public: bool) -> Result<(), SayErrorCode> {
318        SayErrorCode::result_from_i8(self.say_internal(message, public))
319    }
320
321    /// Immediately kill the power creep.
322    ///
323    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.suicide)
324    pub fn suicide(&self) -> Result<(), SuicideErrorCode> {
325        SuicideErrorCode::result_from_i8(self.suicide_internal())
326    }
327
328    /// Use one of the power creep's powers.
329    ///
330    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.usePower)
331    pub fn use_power(
332        &self,
333        power: PowerType,
334        target: Option<&RoomObject>,
335    ) -> Result<(), UsePowerErrorCode> {
336        UsePowerErrorCode::result_from_i8(self.use_power_internal(power, target))
337    }
338
339    /// Move the power creep toward the specified goal, either a
340    /// [`RoomPosition`] or [`RoomObject`]. Note that using this function
341    /// will store data in `Memory.creeps[creep_name]` and enable the
342    /// default serialization behavior of the `Memory` object, which may
343    /// hamper attempts to directly use `RawMemory`.
344    ///
345    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.moveTo)
346    pub fn move_to<T>(&self, target: T) -> Result<(), PowerCreepMoveToErrorCode>
347    where
348        T: HasPosition,
349    {
350        let target: RoomPosition = target.pos().into();
351        PowerCreepMoveToErrorCode::result_from_i8(
352            self.move_to_internal(&target, &JsValue::UNDEFINED),
353        )
354    }
355
356    /// Move the power creep toward the specified goal, either a
357    /// [`RoomPosition`] or [`RoomObject`]. Note that using this function
358    /// will store data in `Memory.creeps[creep_name]` and enable the
359    /// default serialization behavior of the `Memory` object, which may
360    /// hamper attempts to directly use `RawMemory`.
361    ///
362    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.moveTo)
363    pub fn move_to_with_options<T, F>(
364        &self,
365        target: T,
366        options: Option<MoveToOptions<F>>,
367    ) -> Result<(), PowerCreepMoveToErrorCode>
368    where
369        T: HasPosition,
370        F: FnMut(RoomName, CostMatrix) -> SingleRoomCostResult,
371    {
372        let target: RoomPosition = target.pos().into();
373
374        if let Some(options) = options {
375            options.into_js_options(|js_options| {
376                PowerCreepMoveToErrorCode::result_from_i8(
377                    self.move_to_internal(&target, js_options),
378                )
379            })
380        } else {
381            PowerCreepMoveToErrorCode::result_from_i8(
382                self.move_to_internal(&target, &JsValue::UNDEFINED),
383            )
384        }
385    }
386}
387
388impl HasHits for PowerCreep {
389    fn hits(&self) -> u32 {
390        self.hits()
391    }
392
393    fn hits_max(&self) -> u32 {
394        self.hits_max()
395    }
396}
397
398impl HasId for PowerCreep {
399    fn js_raw_id(&self) -> JsString {
400        self.id_internal()
401    }
402}
403
404impl HasStore for PowerCreep {
405    fn store(&self) -> Store {
406        self.store()
407    }
408}
409
410impl Attackable for PowerCreep {}
411impl Healable for PowerCreep {}
412impl Transferable for PowerCreep {}
413
414impl SharedCreepProperties for PowerCreep {
415    fn memory(&self) -> JsValue {
416        self.memory()
417    }
418
419    fn set_memory(&self, val: &JsValue) {
420        self.set_memory(val)
421    }
422
423    fn my(&self) -> bool {
424        self.my()
425    }
426
427    fn name(&self) -> String {
428        self.name_internal()
429    }
430
431    fn name_jsstring(&self) -> JsString {
432        self.name_jsstring_internal()
433    }
434
435    fn owner(&self) -> Owner {
436        self.owner()
437    }
438
439    fn saying(&self) -> Option<JsString> {
440        self.saying()
441    }
442
443    fn ticks_to_live(&self) -> Option<u32> {
444        self.ticks_to_live()
445    }
446
447    fn drop(&self, ty: ResourceType, amount: Option<u32>) -> Result<(), DropErrorCode> {
448        self.drop(ty, amount)
449    }
450
451    fn notify_when_attacked(&self, enabled: bool) -> Result<(), NotifyWhenAttackedErrorCode> {
452        NotifyWhenAttackedErrorCode::result_from_i8(self.notify_when_attacked_internal(enabled))
453    }
454
455    fn pickup(&self, target: &Resource) -> Result<(), PickupErrorCode> {
456        PickupErrorCode::result_from_i8(self.pickup_internal(target))
457    }
458
459    fn say(&self, message: &str, public: bool) -> Result<(), SayErrorCode> {
460        SayErrorCode::result_from_i8(self.say_internal(message, public))
461    }
462
463    fn suicide(&self) -> Result<(), SuicideErrorCode> {
464        SuicideErrorCode::result_from_i8(self.suicide_internal())
465    }
466
467    fn transfer<T>(
468        &self,
469        target: &T,
470        ty: ResourceType,
471        amount: Option<u32>,
472    ) -> Result<(), TransferErrorCode>
473    where
474        T: Transferable + ?Sized,
475    {
476        TransferErrorCode::result_from_i8(self.transfer_internal(target.as_ref(), ty, amount))
477    }
478
479    fn withdraw<T>(
480        &self,
481        target: &T,
482        ty: ResourceType,
483        amount: Option<u32>,
484    ) -> Result<(), WithdrawErrorCode>
485    where
486        T: Withdrawable + ?Sized,
487    {
488        WithdrawErrorCode::result_from_i8(self.withdraw_internal(target.as_ref(), ty, amount))
489    }
490}
491
492#[wasm_bindgen]
493extern "C" {
494    /// A [`PowerCreep`] unit that may or may not be spawned in the current
495    /// shard of the game world.
496    ///
497    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep)
498    #[derive(Clone, Debug)]
499    pub type AccountPowerCreep;
500
501    #[wasm_bindgen(method, getter = id)]
502    fn id_internal(this: &AccountPowerCreep) -> Option<JsString>;
503
504    #[wasm_bindgen(method, getter = className)]
505    fn class_internal(this: &AccountPowerCreep) -> PowerCreepClass;
506
507    #[wasm_bindgen(method, getter = deleteTime)]
508    fn delete_time_internal(this: &AccountPowerCreep) -> Option<f64>;
509
510    #[wasm_bindgen(method, getter = level)]
511    fn level_internal(this: &AccountPowerCreep) -> u32;
512
513    #[wasm_bindgen(method, getter = name)]
514    fn name_internal(this: &AccountPowerCreep) -> String;
515
516    #[wasm_bindgen(method, getter = name)]
517    fn name_jsstring_internal(this: &AccountPowerCreep) -> JsString;
518
519    #[wasm_bindgen(method, getter = powers)]
520    fn powers_internal(this: &AccountPowerCreep) -> Object;
521
522    #[wasm_bindgen(method, getter = shard)]
523    fn shard_internal(this: &AccountPowerCreep) -> Option<JsString>;
524
525    #[wasm_bindgen(method, getter = spawnCooldownTime)]
526    fn spawn_cooldown_time_internal(this: &AccountPowerCreep) -> Option<f64>;
527
528    #[wasm_bindgen(method, js_name = delete)]
529    fn delete_internal(this: &AccountPowerCreep, cancel: bool) -> i8;
530
531    #[wasm_bindgen(method, js_name = rename)]
532    fn rename_internal(this: &AccountPowerCreep, name: &JsString) -> i8;
533
534    #[wasm_bindgen(method, js_name = spawn)]
535    fn spawn_internal(this: &AccountPowerCreep, target: &StructurePowerSpawn) -> i8;
536
537    #[wasm_bindgen(method, js_name = upgrade)]
538    fn upgrade_internal(this: &AccountPowerCreep, power: PowerType) -> i8;
539}
540
541impl AccountPowerCreep {
542    /// Retrieve this power creep's [`PowerCreepClass`].
543    ///
544    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.className)
545    pub fn class(&self) -> PowerCreepClass {
546        self.class_internal()
547    }
548
549    // todo should be u64 but seems to panic at the moment, follow up
550    /// The timestamp, in milliseconds since epoch, when the [`PowerCreep`] will
551    /// be permanently deleted due to [`AccountPowerCreep::delete`]. Can be
552    /// cancelled with the same function until then.
553    ///
554    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.deleteTime)
555    pub fn delete_time(&self) -> Option<f64> {
556        self.delete_time_internal()
557    }
558
559    /// Current level of the power creep, which can be increased with
560    /// [`AccountPowerCreep::upgrade`] if you have unspent GPL.
561    ///
562    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.level)
563    pub fn level(&self) -> u32 {
564        self.level_internal()
565    }
566
567    /// The power creep's name as a [`String`].
568    ///
569    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.name)
570    pub fn name(&self) -> String {
571        self.name_internal()
572    }
573
574    /// The power creep's name as a [`JsString`].
575    ///
576    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.name)
577    pub fn name_jsstring(&self) -> JsString {
578        self.name_jsstring_internal()
579    }
580
581    /// The levels of this power creep's abilities, with [`PowerType`] keys and
582    /// values containing power level and cooldown.
583    ///
584    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.powers)
585    pub fn powers(&self) -> JsHashMap<PowerType, PowerInfo> {
586        self.powers_internal().into()
587    }
588
589    /// The shard the power creep is currently spawned on, if spawned.
590    ///
591    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.shard)
592    pub fn shard(&self) -> Option<JsString> {
593        self.shard_internal()
594    }
595
596    // todo should be u64 but seems to panic at the moment, follow up
597    /// The timestamp, in milliseconds since epoch, when the power creep will be
598    /// allowed to spawn again after dying.
599    ///
600    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.spawnCooldownTime)
601    pub fn spawn_cooldown_time(&self) -> Option<f64> {
602        self.spawn_cooldown_time_internal()
603    }
604
605    /// Set a power creep that is not currently spawned to be deleted. Can be
606    /// cancelled with `true` for the cancel paramater.
607    ///
608    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.delete)
609    pub fn delete(&self, cancel: bool) -> Result<(), DeleteErrorCode> {
610        DeleteErrorCode::result_from_i8(self.delete_internal(cancel))
611    }
612
613    /// Change the name of the power creep. Must not be spawned.
614    ///
615    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.rename)
616    pub fn rename(&self, name: &JsString) -> Result<(), RenameErrorCode> {
617        RenameErrorCode::result_from_i8(self.rename_internal(name))
618    }
619
620    /// Spawn the power creep at a [`StructurePowerSpawn`].
621    ///
622    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.spawn)
623    pub fn spawn(&self, target: &StructurePowerSpawn) -> Result<(), SpawnErrorCode> {
624        SpawnErrorCode::result_from_i8(self.spawn_internal(target))
625    }
626
627    /// Upgrade this power creep, consuming one available GPL and adding a new
628    /// level to one of its powers.
629    ///
630    /// [Screeps documentation](https://docs.screeps.com/api/#PowerCreep.upgrade)
631    pub fn upgrade(&self, power: PowerType) -> Result<(), UpgradeErrorCode> {
632        UpgradeErrorCode::result_from_i8(self.upgrade_internal(power))
633    }
634}
635
636impl JsCollectionFromValue for AccountPowerCreep {
637    fn from_value(val: JsValue) -> Self {
638        val.unchecked_into()
639    }
640}
641
642#[derive(Debug, Clone)]
643pub struct PowerCreepNotSpawned {}
644
645impl fmt::Display for PowerCreepNotSpawned {
646    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
647        write!(f, "PowerCreep not currently spawned")
648    }
649}
650
651impl Error for PowerCreepNotSpawned {}
652
653impl TryFrom<AccountPowerCreep> for PowerCreep {
654    type Error = PowerCreepNotSpawned;
655
656    fn try_from(account_power_creep: AccountPowerCreep) -> Result<Self, Self::Error> {
657        account_power_creep
658            .id_internal()
659            .map(|_| account_power_creep.unchecked_into())
660            .ok_or(PowerCreepNotSpawned {})
661    }
662}
663
664impl AsRef<AccountPowerCreep> for PowerCreep {
665    fn as_ref(&self) -> &AccountPowerCreep {
666        self.unchecked_ref()
667    }
668}
669
670impl From<PowerCreep> for AccountPowerCreep {
671    fn from(power_creep: PowerCreep) -> Self {
672        power_creep.unchecked_into()
673    }
674}
675
676#[wasm_bindgen]
677extern "C" {
678    #[wasm_bindgen]
679    #[derive(Debug)]
680    pub type PowerInfo;
681    #[wasm_bindgen(method, getter)]
682    pub fn cooldown(this: &PowerInfo) -> u32;
683    #[wasm_bindgen(method, getter)]
684    pub fn level(this: &PowerInfo) -> u8;
685}
686
687impl JsCollectionFromValue for PowerInfo {
688    fn from_value(val: JsValue) -> Self {
689        val.unchecked_into()
690    }
691}