screeps/
enums.rs

1//! Enums using [`enum_dispatch`] for generic wrappers around object types with
2//! shared traits.
3//!
4//! [`enum_dispatch`]: enum_dispatch::enum_dispatch
5pub mod action_error_codes;
6
7use enum_dispatch::enum_dispatch;
8use wasm_bindgen::{JsCast, JsValue};
9
10use crate::{objects::*, prelude::*, ResourceType, RESOURCES_ALL};
11
12#[enum_dispatch(Attackable)]
13pub enum AttackableObject {
14    Creep,
15    PowerCreep,
16    StructureContainer,
17    StructureExtension,
18    StructureExtractor,
19    StructureFactory,
20    StructureInvaderCore,
21    StructureLab,
22    StructureLink,
23    StructureNuker,
24    StructureObserver,
25    StructurePowerBank,
26    StructurePowerSpawn,
27    StructureRampart,
28    StructureRoad,
29    StructureSpawn,
30    StructureStorage,
31    StructureTerminal,
32    StructureTower,
33    StructureWall,
34}
35
36impl From<AttackableObject> for RoomObject {
37    fn from(attackable: AttackableObject) -> Self {
38        use AttackableObject::*;
39
40        match attackable {
41            Creep(o) => RoomObject::from(o),
42            PowerCreep(o) => RoomObject::from(o),
43            StructureContainer(o) => RoomObject::from(o),
44            StructureExtension(o) => RoomObject::from(o),
45            StructureExtractor(o) => RoomObject::from(o),
46            StructureFactory(o) => RoomObject::from(o),
47            StructureInvaderCore(o) => RoomObject::from(o),
48            StructureLab(o) => RoomObject::from(o),
49            StructureLink(o) => RoomObject::from(o),
50            StructureNuker(o) => RoomObject::from(o),
51            StructureObserver(o) => RoomObject::from(o),
52            StructurePowerBank(o) => RoomObject::from(o),
53            StructurePowerSpawn(o) => RoomObject::from(o),
54            StructureRampart(o) => RoomObject::from(o),
55            StructureRoad(o) => RoomObject::from(o),
56            StructureSpawn(o) => RoomObject::from(o),
57            StructureStorage(o) => RoomObject::from(o),
58            StructureTerminal(o) => RoomObject::from(o),
59            StructureTower(o) => RoomObject::from(o),
60            StructureWall(o) => RoomObject::from(o),
61        }
62    }
63}
64
65impl AsRef<RoomObject> for AttackableObject {
66    fn as_ref(&self) -> &RoomObject {
67        use AttackableObject::*;
68
69        match self {
70            Creep(o) => o.as_ref(),
71            PowerCreep(o) => o.as_ref(),
72            StructureContainer(o) => o.as_ref(),
73            StructureExtension(o) => o.as_ref(),
74            StructureExtractor(o) => o.as_ref(),
75            StructureFactory(o) => o.as_ref(),
76            StructureInvaderCore(o) => o.as_ref(),
77            StructureLab(o) => o.as_ref(),
78            StructureLink(o) => o.as_ref(),
79            StructureNuker(o) => o.as_ref(),
80            StructureObserver(o) => o.as_ref(),
81            StructurePowerBank(o) => o.as_ref(),
82            StructurePowerSpawn(o) => o.as_ref(),
83            StructureRampart(o) => o.as_ref(),
84            StructureRoad(o) => o.as_ref(),
85            StructureSpawn(o) => o.as_ref(),
86            StructureStorage(o) => o.as_ref(),
87            StructureTerminal(o) => o.as_ref(),
88            StructureTower(o) => o.as_ref(),
89            StructureWall(o) => o.as_ref(),
90        }
91    }
92}
93
94#[enum_dispatch(CanDecay)]
95pub enum DecayingObject {
96    Deposit,
97    Ruin,
98    #[cfg(feature = "seasonal-season-1")]
99    ScoreContainer,
100    StructureContainer,
101    StructurePortal,
102    StructurePowerBank,
103    StructureRampart,
104    StructureRoad,
105    #[cfg(feature = "seasonal-season-2")]
106    SymbolContainer,
107    Tombstone,
108}
109
110#[enum_dispatch(HasCooldown)]
111pub enum CooldownObject {
112    Deposit,
113    StructureExtractor,
114    StructureFactory,
115    StructureLab,
116    StructureLink,
117    StructureNuker,
118    StructureTerminal,
119}
120
121#[enum_dispatch(HasPosition)]
122pub enum ObjectWithPosition {
123    ConstructionSite,
124    Creep,
125    Deposit,
126    Flag,
127    Mineral,
128    Nuke,
129    PowerCreep,
130    Resource,
131    RoomPosition,
132    Ruin,
133    #[cfg(feature = "seasonal-season-1")]
134    ScoreCollector,
135    #[cfg(feature = "seasonal-season-1")]
136    ScoreContainer,
137    Source,
138    StructureContainer,
139    StructureController,
140    StructureExtension,
141    StructureExtractor,
142    StructureFactory,
143    StructureInvaderCore,
144    StructureKeeperLair,
145    StructureLab,
146    StructureLink,
147    StructureNuker,
148    StructureObserver,
149    StructurePortal,
150    StructurePowerBank,
151    StructurePowerSpawn,
152    StructureRampart,
153    StructureRoad,
154    StructureSpawn,
155    StructureStorage,
156    StructureTerminal,
157    StructureTower,
158    StructureWall,
159    #[cfg(feature = "seasonal-season-2")]
160    SymbolContainer,
161    #[cfg(feature = "seasonal-season-2")]
162    SymbolDecoder,
163    Tombstone,
164}
165
166#[enum_dispatch(HasStore)]
167pub enum StoreObject {
168    Creep,
169    PowerCreep,
170    #[cfg(feature = "seasonal-season-5")]
171    Reactor,
172    Ruin,
173    #[cfg(feature = "seasonal-season-1")]
174    ScoreCollector,
175    #[cfg(feature = "seasonal-season-1")]
176    ScoreContainer,
177    StructureContainer,
178    StructureExtension,
179    StructureFactory,
180    StructureLab,
181    StructureLink,
182    StructureNuker,
183    StructurePowerSpawn,
184    StructureSpawn,
185    StructureStorage,
186    StructureTerminal,
187    StructureTower,
188    #[cfg(feature = "seasonal-season-2")]
189    SymbolContainer,
190    Tombstone,
191}
192
193impl StoreObject {
194    /// All possible resources that this store may hold.
195    ///
196    /// Note: [`StructureLab`] is slightly odd in that it can hold any possible
197    /// resource (including non-lab resources like power), but only one
198    /// non-energy resource at a time.
199    ///
200    /// # Example
201    /// Assuming that `store_object` is a [`StoreObject::StructureExtension`]:
202    /// ```no_run
203    /// # use screeps::{ResourceType, StoreObject};
204    /// # let store_object: StoreObject = todo!();
205    /// assert_eq!(store_object.resource_types(), &[ResourceType::Energy]);
206    /// ```
207    /// To access this property from a [`StructureObject`], use the following
208    /// conversion:
209    /// ```no_run
210    /// # use screeps::{ResourceType, StoreObject, StoreObjectConversionError, StructureObject};
211    /// # let structure_object: StructureObject = todo!();
212    /// let ty: Result<&[ResourceType], StoreObjectConversionError> =
213    ///     StoreObject::try_from(structure_object).map(|store_obj| store_obj.resource_types());
214    /// ```
215    ///
216    /// Data collected on 2024-02-29 from <https://github.com/screeps/engine/tree/97c9d12385fed686655c13b09f5f2457dd83a2bf>
217    pub const fn resource_types(&self) -> &'static [ResourceType] {
218        match self {
219            StoreObject::Creep(_) => RESOURCES_ALL,
220            StoreObject::PowerCreep(_) => RESOURCES_ALL,
221            #[cfg(feature = "seasonal-season-5")]
222            StoreObject::Reactor(_) => &[ResourceType::Thorium],
223            StoreObject::Ruin(_) => RESOURCES_ALL,
224            #[cfg(feature = "seasonal-season-1")]
225            StoreObject::ScoreCollector(_) => &[ResourceType::Score],
226            #[cfg(feature = "seasonal-season-1")]
227            StoreObject::ScoreContainer(_) => &[ResourceType::Score],
228            StoreObject::StructureContainer(_) => RESOURCES_ALL,
229            StoreObject::StructureExtension(_) => &[ResourceType::Energy],
230            StoreObject::StructureFactory(_) => RESOURCES_ALL,
231            StoreObject::StructureLab(_) => RESOURCES_ALL,
232            StoreObject::StructureLink(_) => &[ResourceType::Energy],
233            StoreObject::StructureNuker(_) => &[ResourceType::Energy, ResourceType::Ghodium],
234            StoreObject::StructurePowerSpawn(_) => &[ResourceType::Energy, ResourceType::Power],
235            StoreObject::StructureSpawn(_) => &[ResourceType::Energy],
236            StoreObject::StructureStorage(_) => RESOURCES_ALL,
237            StoreObject::StructureTerminal(_) => RESOURCES_ALL,
238            StoreObject::StructureTower(_) => &[ResourceType::Energy],
239            #[cfg(feature = "seasonal-season-2")]
240            StoreObject::SymbolContainer(_) => &crate::constants::seasonal::season_2::SYMBOLS,
241            StoreObject::Tombstone(_) => RESOURCES_ALL,
242        }
243    }
244}
245
246/// Enum used for converting a [`Structure`] into a typed object of its specific
247/// structure type.
248#[enum_dispatch(OwnedStructureProperties)]
249pub enum OwnedStructureObject {
250    StructureController,
251    StructureExtension,
252    StructureExtractor,
253    StructureFactory,
254    StructureInvaderCore,
255    StructureKeeperLair,
256    StructureLab,
257    StructureLink,
258    StructureNuker,
259    StructureObserver,
260    StructurePowerSpawn,
261    StructureRampart,
262    StructureSpawn,
263    StructureStorage,
264    StructureTerminal,
265    StructureTower,
266}
267
268// todo TryFrom<Structure> for OwnedStructureObject
269
270/// Any enum representing any game object that inherits the [`RoomObject`] type.
271#[enum_dispatch(RoomObjectProperties)]
272pub enum TypedRoomObject {
273    ConstructionSite,
274    Creep,
275    Deposit,
276    Flag,
277    Mineral,
278    Nuke,
279    PowerCreep,
280    Resource,
281    Ruin,
282    #[cfg(feature = "seasonal-season-1")]
283    ScoreCollector,
284    #[cfg(feature = "seasonal-season-1")]
285    ScoreContainer,
286    Source,
287    StructureContainer,
288    StructureController,
289    StructureExtension,
290    StructureExtractor,
291    StructureFactory,
292    StructureInvaderCore,
293    StructureKeeperLair,
294    StructureLab,
295    StructureLink,
296    StructureNuker,
297    StructureObserver,
298    StructurePortal,
299    StructurePowerBank,
300    StructurePowerSpawn,
301    StructureRampart,
302    StructureRoad,
303    StructureSpawn,
304    StructureStorage,
305    StructureTerminal,
306    StructureTower,
307    StructureWall,
308    #[cfg(feature = "seasonal-season-2")]
309    SymbolContainer,
310    #[cfg(feature = "seasonal-season-2")]
311    SymbolDecoder,
312    Tombstone,
313}
314
315#[enum_dispatch(SharedCreepProperties)]
316pub enum MovableObject {
317    Creep,
318    PowerCreep,
319}
320
321/// Enum used for converting a [`Structure`] into a typed object of its specific
322/// structure type.
323#[enum_dispatch(StructureProperties, HasPosition)]
324#[derive(Clone, Debug)]
325pub enum StructureObject {
326    StructureContainer,
327    StructureController,
328    StructureExtension,
329    StructureExtractor,
330    StructureFactory,
331    StructureInvaderCore,
332    StructureKeeperLair,
333    StructureLab,
334    StructureLink,
335    StructureNuker,
336    StructureObserver,
337    StructurePortal,
338    StructurePowerBank,
339    StructurePowerSpawn,
340    StructureRampart,
341    StructureRoad,
342    StructureSpawn,
343    StructureStorage,
344    StructureTerminal,
345    StructureTower,
346    StructureWall,
347}
348
349#[enum_dispatch(Transferable)]
350pub enum TransferableObject {
351    StructureExtension,
352    Creep,
353    StructureContainer,
354    StructureFactory,
355    StructureLab,
356    StructureLink,
357    StructureNuker,
358    StructureSpawn,
359    StructureStorage,
360    StructureTower,
361    StructurePowerSpawn,
362    StructureTerminal,
363    PowerCreep,
364}
365
366impl AsRef<RoomObject> for TransferableObject {
367    fn as_ref(&self) -> &RoomObject {
368        use TransferableObject::*;
369
370        match self {
371            StructureExtension(o) => o.as_ref(),
372            Creep(o) => o.as_ref(),
373            StructureContainer(o) => o.as_ref(),
374            StructureFactory(o) => o.as_ref(),
375            StructureLab(o) => o.as_ref(),
376            StructureLink(o) => o.as_ref(),
377            StructureNuker(o) => o.as_ref(),
378            StructureSpawn(o) => o.as_ref(),
379            StructureStorage(o) => o.as_ref(),
380            StructureTower(o) => o.as_ref(),
381            StructurePowerSpawn(o) => o.as_ref(),
382            StructureTerminal(o) => o.as_ref(),
383            PowerCreep(o) => o.as_ref(),
384        }
385    }
386}
387
388impl From<JsValue> for StructureObject {
389    fn from(reference: JsValue) -> Self {
390        let structure: Structure = reference.unchecked_into();
391
392        structure.into()
393    }
394}
395
396impl JsCollectionFromValue for StructureObject {
397    fn from_value(val: JsValue) -> Self {
398        Self::from(val)
399    }
400}
401
402#[derive(Clone, Copy, Debug)]
403pub enum OwnedStructureConversionError {
404    NotOwnable,
405}
406
407impl TryFrom<StructureObject> for OwnedStructureObject {
408    type Error = OwnedStructureConversionError;
409
410    fn try_from(structure: StructureObject) -> Result<Self, Self::Error> {
411        match structure {
412            StructureObject::StructureController(val) => {
413                Ok(OwnedStructureObject::StructureController(val))
414            }
415            StructureObject::StructureExtension(val) => {
416                Ok(OwnedStructureObject::StructureExtension(val))
417            }
418            StructureObject::StructureExtractor(val) => {
419                Ok(OwnedStructureObject::StructureExtractor(val))
420            }
421            StructureObject::StructureFactory(val) => {
422                Ok(OwnedStructureObject::StructureFactory(val))
423            }
424            StructureObject::StructureInvaderCore(val) => {
425                Ok(OwnedStructureObject::StructureInvaderCore(val))
426            }
427            StructureObject::StructureKeeperLair(val) => {
428                Ok(OwnedStructureObject::StructureKeeperLair(val))
429            }
430            StructureObject::StructureLab(val) => Ok(OwnedStructureObject::StructureLab(val)),
431            StructureObject::StructureLink(val) => Ok(OwnedStructureObject::StructureLink(val)),
432            StructureObject::StructureNuker(val) => Ok(OwnedStructureObject::StructureNuker(val)),
433            StructureObject::StructureObserver(val) => {
434                Ok(OwnedStructureObject::StructureObserver(val))
435            }
436            StructureObject::StructurePowerSpawn(val) => {
437                Ok(OwnedStructureObject::StructurePowerSpawn(val))
438            }
439            StructureObject::StructureRampart(val) => {
440                Ok(OwnedStructureObject::StructureRampart(val))
441            }
442            StructureObject::StructureSpawn(val) => Ok(OwnedStructureObject::StructureSpawn(val)),
443            StructureObject::StructureStorage(val) => {
444                Ok(OwnedStructureObject::StructureStorage(val))
445            }
446            StructureObject::StructureTerminal(val) => {
447                Ok(OwnedStructureObject::StructureTerminal(val))
448            }
449            StructureObject::StructureTower(val) => Ok(OwnedStructureObject::StructureTower(val)),
450            StructureObject::StructureContainer(_)
451            | StructureObject::StructureRoad(_)
452            | StructureObject::StructurePortal(_)
453            | StructureObject::StructurePowerBank(_)
454            | StructureObject::StructureWall(_) => Err(OwnedStructureConversionError::NotOwnable),
455        }
456    }
457}
458
459#[derive(Clone, Copy, Debug)]
460pub enum TransferableObjectConversionError {
461    NotTransferable,
462}
463
464impl TryFrom<StructureObject> for TransferableObject {
465    type Error = TransferableObjectConversionError;
466
467    fn try_from(structure: StructureObject) -> Result<Self, Self::Error> {
468        match structure {
469            StructureObject::StructureExtension(val) => Ok(Self::StructureExtension(val)),
470            StructureObject::StructureContainer(val) => Ok(Self::StructureContainer(val)),
471            StructureObject::StructureFactory(val) => Ok(Self::StructureFactory(val)),
472            StructureObject::StructureLab(val) => Ok(Self::StructureLab(val)),
473            StructureObject::StructureLink(val) => Ok(Self::StructureLink(val)),
474            StructureObject::StructureNuker(val) => Ok(Self::StructureNuker(val)),
475            StructureObject::StructureSpawn(val) => Ok(Self::StructureSpawn(val)),
476            StructureObject::StructureStorage(val) => Ok(Self::StructureStorage(val)),
477            StructureObject::StructureTower(val) => Ok(Self::StructureTower(val)),
478            StructureObject::StructurePowerSpawn(val) => Ok(Self::StructurePowerSpawn(val)),
479            StructureObject::StructureTerminal(val) => Ok(Self::StructureTerminal(val)),
480
481            StructureObject::StructureController(_)
482            | StructureObject::StructureExtractor(_)
483            | StructureObject::StructureInvaderCore(_)
484            | StructureObject::StructureKeeperLair(_)
485            | StructureObject::StructureObserver(_)
486            | StructureObject::StructurePortal(_)
487            | StructureObject::StructurePowerBank(_)
488            | StructureObject::StructureRampart(_)
489            | StructureObject::StructureRoad(_)
490            | StructureObject::StructureWall(_) => {
491                Err(TransferableObjectConversionError::NotTransferable)
492            }
493        }
494    }
495}
496
497#[derive(Clone, Copy, Debug)]
498pub enum StoreObjectConversionError {
499    DoesntHaveStore,
500}
501
502impl TryFrom<StructureObject> for StoreObject {
503    type Error = StoreObjectConversionError;
504
505    fn try_from(structure: StructureObject) -> Result<Self, Self::Error> {
506        match structure {
507            StructureObject::StructureContainer(val) => Ok(Self::StructureContainer(val)),
508            StructureObject::StructureExtension(val) => Ok(Self::StructureExtension(val)),
509            StructureObject::StructureFactory(val) => Ok(Self::StructureFactory(val)),
510            StructureObject::StructureLab(val) => Ok(Self::StructureLab(val)),
511            StructureObject::StructureLink(val) => Ok(Self::StructureLink(val)),
512            StructureObject::StructureNuker(val) => Ok(Self::StructureNuker(val)),
513            StructureObject::StructurePowerSpawn(val) => Ok(Self::StructurePowerSpawn(val)),
514            StructureObject::StructureSpawn(val) => Ok(Self::StructureSpawn(val)),
515            StructureObject::StructureStorage(val) => Ok(Self::StructureStorage(val)),
516            StructureObject::StructureTerminal(val) => Ok(Self::StructureTerminal(val)),
517            StructureObject::StructureTower(val) => Ok(Self::StructureTower(val)),
518
519            StructureObject::StructureController(_)
520            | StructureObject::StructureExtractor(_)
521            | StructureObject::StructureInvaderCore(_)
522            | StructureObject::StructureKeeperLair(_)
523            | StructureObject::StructureObserver(_)
524            | StructureObject::StructurePortal(_)
525            | StructureObject::StructurePowerBank(_)
526            | StructureObject::StructureRampart(_)
527            | StructureObject::StructureRoad(_)
528            | StructureObject::StructureWall(_) => Err(StoreObjectConversionError::DoesntHaveStore),
529        }
530    }
531}
532
533impl From<Structure> for StructureObject {
534    fn from(structure: Structure) -> Self {
535        use crate::constants::StructureType::*;
536
537        match structure.structure_type() {
538            Container => Self::StructureContainer(structure.unchecked_into()),
539            Controller => Self::StructureController(structure.unchecked_into()),
540            Extension => Self::StructureExtension(structure.unchecked_into()),
541            Extractor => Self::StructureExtractor(structure.unchecked_into()),
542            Factory => Self::StructureFactory(structure.unchecked_into()),
543            InvaderCore => Self::StructureInvaderCore(structure.unchecked_into()),
544            KeeperLair => Self::StructureKeeperLair(structure.unchecked_into()),
545            Lab => Self::StructureLab(structure.unchecked_into()),
546            Link => Self::StructureLink(structure.unchecked_into()),
547            Nuker => Self::StructureNuker(structure.unchecked_into()),
548            Observer => Self::StructureObserver(structure.unchecked_into()),
549            Portal => Self::StructurePortal(structure.unchecked_into()),
550            PowerBank => Self::StructurePowerBank(structure.unchecked_into()),
551            PowerSpawn => Self::StructurePowerSpawn(structure.unchecked_into()),
552            Rampart => Self::StructureRampart(structure.unchecked_into()),
553            Road => Self::StructureRoad(structure.unchecked_into()),
554            Spawn => Self::StructureSpawn(structure.unchecked_into()),
555            Storage => Self::StructureStorage(structure.unchecked_into()),
556            Terminal => Self::StructureTerminal(structure.unchecked_into()),
557            Tower => Self::StructureTower(structure.unchecked_into()),
558            Wall => Self::StructureWall(structure.unchecked_into()),
559            _ => panic!("unknown structure type for conversion into enum"),
560        }
561    }
562}
563
564impl StructureObject {
565    pub fn as_structure(&self) -> &Structure {
566        match self {
567            Self::StructureSpawn(s) => s.as_ref(),
568            Self::StructureExtension(s) => s.as_ref(),
569            Self::StructureRoad(s) => s.as_ref(),
570            Self::StructureWall(s) => s.as_ref(),
571            Self::StructureRampart(s) => s.as_ref(),
572            Self::StructureKeeperLair(s) => s.as_ref(),
573            Self::StructurePortal(s) => s.as_ref(),
574            Self::StructureController(s) => s.as_ref(),
575            Self::StructureLink(s) => s.as_ref(),
576            Self::StructureStorage(s) => s.as_ref(),
577            Self::StructureTower(s) => s.as_ref(),
578            Self::StructureObserver(s) => s.as_ref(),
579            Self::StructurePowerBank(s) => s.as_ref(),
580            Self::StructurePowerSpawn(s) => s.as_ref(),
581            Self::StructureExtractor(s) => s.as_ref(),
582            Self::StructureLab(s) => s.as_ref(),
583            Self::StructureTerminal(s) => s.as_ref(),
584            Self::StructureContainer(s) => s.as_ref(),
585            Self::StructureNuker(s) => s.as_ref(),
586            Self::StructureFactory(s) => s.as_ref(),
587            Self::StructureInvaderCore(s) => s.as_ref(),
588        }
589    }
590
591    pub fn as_owned(&self) -> Option<&dyn OwnedStructureProperties> {
592        match self {
593            Self::StructureSpawn(s) => Some(s),
594            Self::StructureExtension(s) => Some(s),
595            Self::StructureRoad(_) => None,
596            Self::StructureWall(_) => None,
597            Self::StructureRampart(s) => Some(s),
598            Self::StructureKeeperLair(s) => Some(s),
599            Self::StructurePortal(_) => None,
600            Self::StructureController(s) => Some(s),
601            Self::StructureLink(s) => Some(s),
602            Self::StructureStorage(s) => Some(s),
603            Self::StructureTower(s) => Some(s),
604            Self::StructureObserver(s) => Some(s),
605            Self::StructurePowerBank(_) => None,
606            Self::StructurePowerSpawn(s) => Some(s),
607            Self::StructureExtractor(s) => Some(s),
608            Self::StructureLab(s) => Some(s),
609            Self::StructureTerminal(s) => Some(s),
610            Self::StructureContainer(_) => None,
611            Self::StructureNuker(s) => Some(s),
612            Self::StructureFactory(s) => Some(s),
613            Self::StructureInvaderCore(s) => Some(s),
614        }
615    }
616
617    pub fn as_has_store(&self) -> Option<&dyn HasStore> {
618        match self {
619            Self::StructureSpawn(s) => Some(s),
620            Self::StructureExtension(s) => Some(s),
621            Self::StructureRoad(_) => None,
622            Self::StructureWall(_) => None,
623            Self::StructureRampart(_) => None,
624            Self::StructureKeeperLair(_) => None,
625            Self::StructurePortal(_) => None,
626            Self::StructureController(_) => None,
627            Self::StructureLink(s) => Some(s),
628            Self::StructureStorage(s) => Some(s),
629            Self::StructureTower(s) => Some(s),
630            Self::StructureObserver(_) => None,
631            Self::StructurePowerBank(_) => None,
632            Self::StructurePowerSpawn(s) => Some(s),
633            Self::StructureExtractor(_) => None,
634            Self::StructureLab(s) => Some(s),
635            Self::StructureTerminal(s) => Some(s),
636            Self::StructureContainer(s) => Some(s),
637            Self::StructureNuker(s) => Some(s),
638            Self::StructureFactory(s) => Some(s),
639            Self::StructureInvaderCore(_) => None,
640        }
641    }
642
643    pub fn as_transferable(&self) -> Option<&dyn Transferable> {
644        match self {
645            Self::StructureSpawn(s) => Some(s),
646            Self::StructureExtension(s) => Some(s),
647            Self::StructureRoad(_) => None,
648            Self::StructureWall(_) => None,
649            Self::StructureRampart(_) => None,
650            Self::StructureKeeperLair(_) => None,
651            Self::StructurePortal(_) => None,
652            Self::StructureController(_) => None,
653            Self::StructureLink(s) => Some(s),
654            Self::StructureStorage(s) => Some(s),
655            Self::StructureTower(s) => Some(s),
656            Self::StructureObserver(_) => None,
657            Self::StructurePowerBank(_) => None,
658            Self::StructurePowerSpawn(s) => Some(s),
659            Self::StructureExtractor(_) => None,
660            Self::StructureLab(s) => Some(s),
661            Self::StructureTerminal(s) => Some(s),
662            Self::StructureContainer(s) => Some(s),
663            Self::StructureNuker(s) => Some(s),
664            Self::StructureFactory(s) => Some(s),
665            Self::StructureInvaderCore(_) => None,
666        }
667    }
668
669    pub fn as_withdrawable(&self) -> Option<&dyn Withdrawable> {
670        match self {
671            Self::StructureSpawn(s) => Some(s),
672            Self::StructureExtension(s) => Some(s),
673            Self::StructureRoad(_) => None,
674            Self::StructureWall(_) => None,
675            Self::StructureRampart(_) => None,
676            Self::StructureKeeperLair(_) => None,
677            Self::StructurePortal(_) => None,
678            Self::StructureController(_) => None,
679            Self::StructureLink(s) => Some(s),
680            Self::StructureStorage(s) => Some(s),
681            Self::StructureTower(s) => Some(s),
682            Self::StructureObserver(_) => None,
683            Self::StructurePowerBank(_) => None,
684            Self::StructurePowerSpawn(s) => Some(s),
685            Self::StructureExtractor(_) => None,
686            Self::StructureLab(s) => Some(s),
687            Self::StructureTerminal(s) => Some(s),
688            Self::StructureContainer(s) => Some(s),
689            Self::StructureNuker(_) => None,
690            Self::StructureFactory(s) => Some(s),
691            Self::StructureInvaderCore(_) => None,
692        }
693    }
694
695    pub fn as_attackable(&self) -> Option<&dyn Attackable> {
696        match self {
697            Self::StructureSpawn(s) => Some(s),
698            Self::StructureExtension(s) => Some(s),
699            Self::StructureRoad(s) => Some(s),
700            Self::StructureWall(s) => Some(s),
701            Self::StructureRampart(s) => Some(s),
702            Self::StructureKeeperLair(s) => Some(s),
703            Self::StructurePortal(_) => None,
704            Self::StructureController(_) => None,
705            Self::StructureLink(s) => Some(s),
706            Self::StructureStorage(s) => Some(s),
707            Self::StructureTower(s) => Some(s),
708            Self::StructureObserver(s) => Some(s),
709            Self::StructurePowerBank(s) => Some(s),
710            Self::StructurePowerSpawn(s) => Some(s),
711            Self::StructureExtractor(s) => Some(s),
712            Self::StructureLab(s) => Some(s),
713            Self::StructureTerminal(s) => Some(s),
714            Self::StructureContainer(s) => Some(s),
715            Self::StructureNuker(s) => Some(s),
716            Self::StructureFactory(s) => Some(s),
717            Self::StructureInvaderCore(s) => Some(s),
718        }
719    }
720
721    pub fn as_repairable(&self) -> Option<&dyn Repairable> {
722        match self {
723            Self::StructureSpawn(s) => Some(s),
724            Self::StructureExtension(s) => Some(s),
725            Self::StructureRoad(s) => Some(s),
726            Self::StructureWall(s) => Some(s),
727            Self::StructureRampart(s) => Some(s),
728            Self::StructureKeeperLair(_) => None,
729            Self::StructurePortal(_) => None,
730            Self::StructureController(_) => None,
731            Self::StructureLink(s) => Some(s),
732            Self::StructureStorage(s) => Some(s),
733            Self::StructureTower(s) => Some(s),
734            Self::StructureObserver(s) => Some(s),
735            Self::StructurePowerBank(s) => Some(s),
736            Self::StructurePowerSpawn(s) => Some(s),
737            Self::StructureExtractor(s) => Some(s),
738            Self::StructureLab(s) => Some(s),
739            Self::StructureTerminal(s) => Some(s),
740            Self::StructureContainer(s) => Some(s),
741            Self::StructureNuker(s) => Some(s),
742            Self::StructureFactory(s) => Some(s),
743            Self::StructureInvaderCore(_) => None,
744        }
745    }
746
747    pub fn as_dismantleable(&self) -> Option<&dyn Dismantleable> {
748        match self {
749            Self::StructureSpawn(s) => Some(s),
750            Self::StructureExtension(s) => Some(s),
751            Self::StructureRoad(s) => Some(s),
752            Self::StructureWall(s) => Some(s),
753            Self::StructureRampart(s) => Some(s),
754            Self::StructureKeeperLair(_) => None,
755            Self::StructurePortal(_) => None,
756            Self::StructureController(_) => None,
757            Self::StructureLink(s) => Some(s),
758            Self::StructureStorage(s) => Some(s),
759            Self::StructureTower(s) => Some(s),
760            Self::StructureObserver(s) => Some(s),
761            Self::StructurePowerBank(s) => Some(s),
762            Self::StructurePowerSpawn(s) => Some(s),
763            Self::StructureExtractor(s) => Some(s),
764            Self::StructureLab(s) => Some(s),
765            Self::StructureTerminal(s) => Some(s),
766            Self::StructureContainer(s) => Some(s),
767            Self::StructureNuker(s) => Some(s),
768            Self::StructureFactory(s) => Some(s),
769            Self::StructureInvaderCore(_) => None,
770        }
771    }
772}