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 #[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 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 pub fn class(&self) -> PowerCreepClass {
153 self.class_internal()
154 }
155
156 pub fn hits(&self) -> u32 {
160 self.hits_internal()
161 }
162
163 pub fn hits_max(&self) -> u32 {
167 self.hits_max_internal()
168 }
169
170 pub fn level(&self) -> u32 {
175 self.level_internal()
176 }
177
178 pub fn memory(&self) -> JsValue {
182 self.memory_internal()
183 }
184
185 pub fn set_memory(&self, val: &JsValue) {
189 self.set_memory_internal(val)
190 }
191
192 pub fn my(&self) -> bool {
196 self.my_internal()
197 }
198
199 pub fn owner(&self) -> Owner {
203 self.owner_internal()
204 }
205
206 pub fn powers(&self) -> JsHashMap<PowerType, PowerInfo> {
211 self.powers_internal().into()
212 }
213
214 pub fn saying(&self) -> Option<JsString> {
218 self.saying_internal()
219 }
220
221 pub fn store(&self) -> Store {
226 self.store_internal()
227 }
228
229 pub fn shard(&self) -> Option<JsString> {
233 self.shard_internal()
234 }
235
236 pub fn ticks_to_live(&self) -> Option<u32> {
243 self.ticks_to_live_internal()
244 }
245
246 pub fn cancel_order(&self, target: &JsString) -> Result<(), PowerCreepCancelOrderErrorCode> {
252 PowerCreepCancelOrderErrorCode::result_from_i8(self.cancel_order_internal(target))
253 }
254
255 pub fn drop(&self, ty: ResourceType, amount: Option<u32>) -> Result<(), DropErrorCode> {
259 DropErrorCode::result_from_i8(self.drop_internal(ty, amount))
260 }
261
262 pub fn enable_room(&self, target: &StructureController) -> Result<(), EnableRoomErrorCode> {
267 EnableRoomErrorCode::result_from_i8(self.enable_room_internal(target))
268 }
269
270 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 pub fn move_by_path(&self, path: &JsValue) -> Result<(), PowerCreepMoveByPathErrorCode> {
285 PowerCreepMoveByPathErrorCode::result_from_i8(self.move_by_path_internal(path))
286 }
287
288 pub fn notify_when_attacked(&self, enabled: bool) -> Result<(), NotifyWhenAttackedErrorCode> {
292 NotifyWhenAttackedErrorCode::result_from_i8(self.notify_when_attacked_internal(enabled))
293 }
294
295 pub fn pickup(&self, target: &Resource) -> Result<(), PickupErrorCode> {
300 PickupErrorCode::result_from_i8(self.pickup_internal(target))
301 }
302
303 pub fn renew(&self, target: &RoomObject) -> Result<(), RenewErrorCode> {
310 RenewErrorCode::result_from_i8(self.renew_internal(target))
311 }
312
313 pub fn say(&self, message: &str, public: bool) -> Result<(), SayErrorCode> {
318 SayErrorCode::result_from_i8(self.say_internal(message, public))
319 }
320
321 pub fn suicide(&self) -> Result<(), SuicideErrorCode> {
325 SuicideErrorCode::result_from_i8(self.suicide_internal())
326 }
327
328 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 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 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 #[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 pub fn class(&self) -> PowerCreepClass {
546 self.class_internal()
547 }
548
549 pub fn delete_time(&self) -> Option<f64> {
556 self.delete_time_internal()
557 }
558
559 pub fn level(&self) -> u32 {
564 self.level_internal()
565 }
566
567 pub fn name(&self) -> String {
571 self.name_internal()
572 }
573
574 pub fn name_jsstring(&self) -> JsString {
578 self.name_jsstring_internal()
579 }
580
581 pub fn powers(&self) -> JsHashMap<PowerType, PowerInfo> {
586 self.powers_internal().into()
587 }
588
589 pub fn shard(&self) -> Option<JsString> {
593 self.shard_internal()
594 }
595
596 pub fn spawn_cooldown_time(&self) -> Option<f64> {
602 self.spawn_cooldown_time_internal()
603 }
604
605 pub fn delete(&self, cancel: bool) -> Result<(), DeleteErrorCode> {
610 DeleteErrorCode::result_from_i8(self.delete_internal(cancel))
611 }
612
613 pub fn rename(&self, name: &JsString) -> Result<(), RenameErrorCode> {
617 RenameErrorCode::result_from_i8(self.rename_internal(name))
618 }
619
620 pub fn spawn(&self, target: &StructurePowerSpawn) -> Result<(), SpawnErrorCode> {
624 SpawnErrorCode::result_from_i8(self.spawn_internal(target))
625 }
626
627 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}