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