diff --git a/.gitignore b/.gitignore index 088ba6b..21d6268 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +/card-data/ + # Generated by Cargo # will have compiled files and executables /target/ diff --git a/src/data/schema.rs b/src/data/schema.rs deleted file mode 100644 index 2d8ca21..0000000 --- a/src/data/schema.rs +++ /dev/null @@ -1,219 +0,0 @@ -use std::collections::HashMap; - -/// A single Legends of Runeterra card as represented in the data files from [Data Dragon](https://developer.riotgames.com/docs/lor). -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -#[serde(rename_all="camelCase")] -pub struct Card { - - /// Codes of other cards associated with this one. - /// - /// To access references to the cards themselves, use [associated_cards]. - #[serde(rename = "associated_card_refs")] - pub associated_card_codes: Vec, - - /// Art assets of this card. - pub assets: Vec, - - /// Regions this card belongs to. - #[serde(rename = "region_refs")] - pub regions: Vec, - - /// Base attack of the card. - pub attack: u64, - /// Base cost of the card. - pub cost: u64, - /// Base health of the card. - pub health: u64, - - /// Localized description of the card, in XML. - pub description: String, - /// Localized description of the card, in plain text. - pub description_raw: String, - - /// Localized level up text of the card, in XML. - pub levelup_description: String, - /// Localized level up text of the card, in plain text. - pub levelup_description_raw: String, - - /// Flavor text of the card, displayed when its image is inspected. - pub flavor_text: String, - /// Name of the artist who drew the card. - pub artist_name: String, - - /// Localized name of the card. - pub name: String, - /// Unique seven-character identifier of the card. - #[serde(rename = "card_code")] - pub code: String, - - /// List of keywords of this card, with their localized names. - pub keywords: Vec, - /// List of keywords of this card, with their internal names. - pub keyword_refs: Vec, - - /// [SpellSpeed] of the card. - #[serde(rename = "spell_speed_ref")] - pub spell_speed: SpellSpeed, - - /// [CardRarity] of the card. - #[serde(rename = "rarity_ref")] - pub rarity: CardRarity, - - /// The subtypes the card has, such as `PORO`. - pub subtypes: Vec, - /// The [CardSupertype] the card belongs to, such as `Champion`. - pub supertype: String, - - /// If `true`, the card can be found in chests, crafted, or used in decks. - /// If `false`, the card is not available for direct use, as it is probably created by another card. - pub collectible: bool, - - /// The [CardSet] the card belongs to. - pub set: String, - - #[serde(rename(serialize = "type", deserialize = "type"))] - pub card_type: CardType, -} - - -impl Card { - /// Get references to the cards associated with this one, given an hashmap of all cards. - pub fn associated_cards<'c, 'hm: 'c>(&'c self, hashmap: &'hm HashMap) -> impl Iterator> + 'c { - self.associated_card_codes.iter().map(|r| hashmap.get(r)) - } -} - - -/// A region to which cards can belong to. -#[non_exhaustive] -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -pub enum CardRegion { - /// Noxus. - Noxus, - /// Demacia. - Demacia, - /// Freljord. - Freljord, - /// Shadow Isles. - ShadowIsles, - /// Targon. - Targon, - /// Ionia. - Ionia, - /// Shurima. - Shurima, - /// Piltover & Zaun. - PiltoverZaun, - /// Bandle City. - BandleCity, - - /// Runeterra. - Runeterra, - - /// Origin: The Virtuoso. - Jhin, - /// Origin: Agony's Embrace. - Evelynn, - /// Origin: The Wandering Caretaker. - Bard, - - /// Unsupported region. - #[serde(other)] - Unsupported, -} - - -/// An art asset associated with a given card. -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -#[serde(rename_all="camelCase")] -pub struct Asset { - /// URL to the card art as it is displayed in-game. - pub game_absolute_path: String, - /// URL to the full-size card art as it is displayed when the card is inspected. - pub full_absolute_path: String, -} - - -/// A possible card type. -#[non_exhaustive] -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -pub enum CardType { - /// A spell. - Spell, - /// An unit: either a minion, or a champion. - /// Champions have their `supertype` set to `Champion`, and their `rarity` set to `Champion` as well. - Unit, - /// An ability triggered by an unit. - Ability, - /// A landmark. - Landmark, - /// A trap or boon. - Trap, - - /// Unsupported card type. - #[serde(other)] - Unsupported, -} - - -/// A possible card rarity. -#[non_exhaustive] -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -pub enum CardRarity { - /// The card has no rarity, as it probably is not collectible. - #[serde(alias = "NONE")] - None, - /// A common card. - #[serde(alias = "COMMON")] - Common, - /// A rare card. - #[serde(alias = "RARE")] - Rare, - /// An epic card. - #[serde(alias = "EPIC")] - Epic, - /// A champion. - #[serde(alias = "CHAMPION")] - Champion, - - /// Unsupported card rarity. - #[serde(other)] - Unsupported, -} - - -/// Possible spell speeds. -#[non_exhaustive] -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -pub enum SpellSpeed { - /// Non-spell cards have this speed. - #[serde(alias = "")] - None, - - Slow, - Fast, - - /// Both Focus and Burst cards have `Burst` speed; to disambiguate between the two, check for the `Focus` keyword. - Burst, -} - - -/// Release sets [Card]s may belong to. -#[non_exhaustive] -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] -pub enum CardSet { - #[serde(rename = "Set1")] - Foundations, - #[serde(rename = "Set2")] - RisingTides, - #[serde(rename = "Set3")] - CallOfTheMountain, - #[serde(rename = "Set4")] - EmpiresOfTheAscended, - #[serde(rename = "Set5")] - BeyondTheBandlewood, - #[serde(rename = "Set6")] - Worldwalker, - #[serde(rename = "SetEvent")] - Events, -} diff --git a/src/data/schema/art.rs b/src/data/schema/art.rs new file mode 100644 index 0000000..a3f87f4 --- /dev/null +++ b/src/data/schema/art.rs @@ -0,0 +1,54 @@ +//! Module defining [CardArt]. + +/// An art asset associated with a [Card]. +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub struct CardArt { + /// URL to the `.png` image of the rendered card. + /// + /// # Example + /// + /// `https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001.png` + /// + #[serde(rename = "gameAbsolutePath")] + pub card_png: String, + + /// URL to the `.png` image of the full card art. + /// + /// # Example + /// + /// `https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001-full.png` + /// + #[serde(rename = "fullAbsolutePath")] + pub full_png: String, +} + + +impl CardArt { + /// URL to the `.jpg` image of the rendered card, via `poro.steffo.eu`. + /// + /// Please do not overload this endpoint, as it currently does not use a CDN! + /// + /// # Example + /// + /// `https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001.jpg` + /// + pub fn card_jpg(&self) -> String { + self.card_png + .replace("https://dd.b.pvp.net/latest/set1", "https://poro.steffo.eu/set1-en_us") + .replace(".png", ".jpg") + } + + /// URL to the `.jpg` image of the full card art, via `poro.steffo.eu`. + /// + /// Please do not overload this endpoint, as it currently does not use a CDN! + /// + /// # Example + /// + /// `https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001-full.jpg` + /// + pub fn full_jpg(&self) -> String { + self.full_png + .replace("https://dd.b.pvp.net/latest/set1", "https://poro.steffo.eu/set1-en_us") + .replace(".png", ".jpg") + } +} \ No newline at end of file diff --git a/src/data/schema/card.rs b/src/data/schema/card.rs new file mode 100644 index 0000000..02371e5 --- /dev/null +++ b/src/data/schema/card.rs @@ -0,0 +1,128 @@ +//! Module defining [Card]. + +use std::collections::HashMap; +use super::art::CardArt; +use super::set::CardSet; +use super::r#type::CardType; +use super::region::CardRegion; +use super::keyword::CardKeyword; +use super::rarity::CardRarity; +use super::speed::SpellSpeed; + +/// A single Legends of Runeterra card as represented in the data files from [Data Dragon](https://developer.riotgames.com/docs/lor). +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +#[serde(rename_all="camelCase")] +pub struct Card { + /// Unique seven-character identifier of the card. + #[serde(rename = "card_code")] + pub code: String, + + /// Localized name of the card. + pub name: String, + + /// The [CardType] of the card. + #[serde(rename = "type")] + pub r#type: CardType, + + /// The [CardSet] the card belongs to. + pub set: CardSet, + + /// [CardRarity] of the card. + #[serde(rename = "rarityRef")] + pub rarity: CardRarity, + + /// If `true`, the card can be found in chests, crafted, or used in decks. + /// If `false`, the card is not available for direct use, as it is probably created by another card. + pub collectible: bool, + + /// Regions this card belongs to. + #[serde(rename = "regionRefs")] + pub regions: Vec, + /// Localized names of the regions this card belongs to. + #[deprecated = "Only for re-serialization purposes, use regions instead!"] + #[serde(rename = "regions")] + pub regions_localized: Vec, + + /// A [Vec] of [CardArt] assets of the card. + /// + /// Should always contain at least an element; may sometimes contain two or more. + /// + /// To quickly access the first element, use [main_art]. + #[serde(rename = "assets")] + pub art: Vec, + + /// Base attack of the card. + pub attack: u64, + + /// Base cost of the card. + pub cost: u64, + + /// Base health of the card. + pub health: u64, + + /// [SpellSpeed] of the card. + #[serde(rename = "spell_speed_ref")] + pub spell_speed: SpellSpeed, + /// Localized name of the [SpellSpeed] of the card. + #[deprecated = "Only for re-serialization purposes, use spell_speed instead!"] + pub spell_speed_localized: String, + + /// List of keywords of this card. + #[serde(rename="keyword_refs")] + pub keywords: Vec, + /// Localized names of keywords of this card. + #[deprecated = "Only for re-serialization purposes, use keywords instead!"] + #[serde(rename="keywords")] + pub keywords_localized: Vec, + + /// Localized description of the card, in XML. + pub description: String, + /// Localized description of the card, in plain text. + pub description_raw: String, + + /// Localized level up text of the card, in XML. + /// + /// If the card has no level up text, contains an empty string. + pub levelup_description: String, + /// Localized level up text of the card, in plain text. + /// + /// If the card has no level up text, contains an empty string. + pub levelup_description_raw: String, + + /// [Codes](code) of other cards associated with this one. + /// + /// To access references to the cards themselves, use [associated_cards]. + #[serde(rename = "associatedCardRefs")] + pub associated_card_codes: Vec, + /// [Names](name) of other cards associated with this one. + #[deprecated = "Only for re-serialization purposes, use associated_card_codes instead!"] + #[serde(rename = "associatedCards")] + pub associated_card_names_localized: Vec, + + /// Flavor text of the card, displayed when its image is inspected. + pub flavor_text: String, + /// Name of the artist who drew the card. + pub artist_name: String, + + /// The subtypes the card has, such as `PORO`. + pub subtypes: Vec, + /// The [CardSupertype] the card belongs to, such as `Champion`. + pub supertype: String, +} + + +impl Card { + /// Get references to the cards associated with this one, given an hashmap of all cards. + pub fn associated_cards<'c, 'hm: 'c>(&'c self, hashmap: &'hm HashMap) -> impl Iterator> + 'c { + self.associated_card_codes.iter().map(|r| hashmap.get(r)) + } + + /// Get a reference to the first [CardArt] of the card. + /// + /// # Panics + /// + /// If the card has no associated [CardArt]. + pub fn main_art(&self) -> &CardArt { + self.art.get(0).expect("card to have at least one art asset") + } +} \ No newline at end of file diff --git a/src/data/schema/keyword.rs b/src/data/schema/keyword.rs new file mode 100644 index 0000000..3e9340f --- /dev/null +++ b/src/data/schema/keyword.rs @@ -0,0 +1,333 @@ +//! Module defining [CardKeyword]. + +/// A keyword which cards can have. +/// +/// Since more keywords will probably be added in the future, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute). +#[non_exhaustive] +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum CardKeyword { + /// Overwhelm on spells. + /// + /// > Inflicts damage beyond what would kill the target(s) to the enemy Nexus. + SpellOverwhelm, + + /// [SpellSpeed::Burst]. + /// + /// > Can be played whenever you may act. Happens instantly and allows you to continue to play other cards. + Burst, + + /// Countdown. + /// + /// > Round Start: I count down 1. At 0, activate the Countdown effect, then destroy me. + Countdown, + + /// "Marked" play. + /// + /// > Get this effect when you play this unit from hand. + #[serde(rename = "PlaySkillMark")] + OnPlay, + + /// [CardType::Landmark]. + /// + /// > Landmarks take up a space on the board. They can't attack, block, or take damage. + #[serde(rename = "LandmarkVisualOnly")] + Landmark, + + /// ??? + Shurima, + + /// Attach. + /// + /// > Attach me to an ally to give it my stats and keywords while I'm attached. When that ally leaves play, Recall me. + Attach, + + /// ??? + Noxus, + + /// Fleeting cards discard from hand when the round ends. + Fleeting, + + /// ?????? + ClobberNoEmptySlotRequirement, + + /// Nab. + /// + /// > Draw a non-champion card from the bottom of the enemy deck. + Nab, + + /// Focus. + /// + /// Used to disambiguate between Burst and Focus with [SpellSpeed::Burst]. + /// + /// > Can be played outside combat or when no other spells or skills are pending. Happens instantly and allows you to continue to play other cards. + Focus, + + /// Enlightened. + /// + /// > You're Enlightened when you have 10 max mana. + Enlightened, + + /// Invoke. + /// + /// > Pick a Celestial card from among 3 to create in hand. + Invoke, + + /// Boon. + /// + /// > Attaches to another card in a deck. When that card is drawn, activate the effect. + Boon, + + /// Trap. + /// + /// > Attaches to another card in a deck. When that card is drawn, activate the effect. + #[serde(rename = "Autoplay")] + Trap, + + /// Drain. + /// + /// > Heal your Nexus for the amount of damage dealt. + Drain, + + /// Last Breath. + /// + /// > These abilities take effect when the unit dies. + LastBreath, + + /// ??? + Demacia, + + /// ??? + BandleCity, + + /// [SpellSpeed::Fast]. + /// + /// > Can be played whenever you may act. Happens after your opponent has a chance to react. + Fast, + + /// ??? + Bilgewater, + + /// ??? + Runeterra, + + /// Recall. + /// + /// > Return a unit to hand and remove all effects applied to it. + Recall, + + /// Weakest. + /// + /// > Lowest Power, with ties broken by lowest Health then lowest Cost + Weakest, + + /// Support. + /// + /// > Attacking with a support unit will buff the unit to its right. + Support, + + /// Slow. + /// + /// > Can be played outside of combat when no spells or skills are pending. Happens after your opponent has a chance to react. + Slow, + + /// Obliterate. + /// + /// > Completely removed from the game. Doesn't cause Last Breath and can't be revived. + Obliterate, + + /// Imbue, an unused keyword. + /// + /// > These abilities trigger when you resolve a spell. + Imbue, + + /// ??? + #[serde(rename = "MtTargon")] + Targon, + + /// ??? + ShadowIsles, + + /// ?????? + AuraVisualFakeKeyword, + + /// ??? + Ionia, + + /// Nightfall. + /// + /// > Bonus if this is NOT the first card you play in a round. + Nightfall, + + /// ??? + PiltoverZaun, + + /// Attune. + /// + /// > When I'm summoned, refill 1 spell mana. + Attune, + + /// Daybreak. + /// + /// > Bonus if this is the FIRST card you play in a round. + Daybreak, + + /// ??? + SilenceIndividualKeyword, + + /// Skill. + /// + /// > A unit's spell-like effect that allows enemy reactions. + Skill, + + /// Plunder, + /// + /// > A card triggers its plunder ability when played if you damaged the enemy Nexus this round. + Plunder, + + /// Double Attack. + /// + /// > While attacking, it strikes both before AND at the same time as its blocker. + DoubleAttack, + + /// Vulnerable. + /// + /// > The enemy can challenge this unit, forcing it to block. + Vulnerable, + + /// Elusive. + /// + /// > Can only be blocked by an Elusive unit. + Elusive, + + /// Stun. + /// + /// > Remove a unit from combat. It can't attack or block for the rest of the round. + Stun, + + /// Fated. + /// + /// > Each round, the first time an allied card targets me, grant me +1|+1. + Fated, + + /// ??? + /// + /// > Can block Elusives. + BlockElusive, + + /// Fury. + /// + /// > When I kill a unit, grant me +1|+1. + Fury, + + /// Barrier. + /// + /// > Negates the next damage the unit would take. Lasts one round. + Barrier, + + /// Immobile. + /// + /// > Can't attack or block. + Immobile, + + /// Hallowed. + /// + /// > After I die, for the rest of the game when allies attack, hallow your first attacker giving it +1|+0 that round. + Hallowed, + + /// Evolve. + /// + /// > I have +2|+2 once you've given or summoned allies with 6+ other positive keywords this game. + Evolve, + + /// Frostbite. + /// + /// > Set a unit's Power to 0 this round. It can be changed after. + Frostbite, + + /// Overwhelm on units. + /// + /// > Excess damage I deal to my blocker is dealt to the enemy Nexus. + Overwhelm, + + /// Quick Attack. + /// + /// > While attacking, strikes before its blocker. + #[serde(rename="QuickStrike")] + QuickAttack, + + /// Tough. + /// + /// > Takes 1 less damage from all sources. + Tough, + + /// Regeneration. + /// + /// > Heals fully at the end of each round. + Regeneration, + + /// Silenced. + /// + /// > Removes all text and keywords from a unit. + Silenced, + + /// SpellShield. + /// + /// > Negates the next enemy spell or skill that would affect me. + SpellShield, + + /// Lifesteal. + /// + /// > Damage this unit deals heals its Nexus that amount. + Lifesteal, + + /// Augment. + /// + /// > When you play a created card, grant me +1|+0. + Augment, + + /// Impact. + /// + /// > When this strikes while attacking, it deals 1 to the enemy Nexus. This keyword can stack. + Impact, + + /// Scout. + /// + /// > The first time only Scout units attack each round, ready your attack. + Scout, + + /// Ephemereal. + /// + /// > This unit dies when it strikes or when the round ends. + Ephemeral, + + /// Lurk. + /// + /// > When you attack while I'm on top of your deck, I Lurk, granting Lurker allies everywhere +1|+0. Max once per round. + #[serde(rename="Lurker")] + Lurk, + + /// Formidable. + /// + /// > I strike with my Health instead of my Power. + Formidable, + + /// Challenger. + /// + /// > Can choose which enemy unit blocks. + Challenger, + + /// Fearsome. + /// + /// > Can only be blocked by enemies with 3 or more Power. + Fearsome, + + /// Can't Block. + CantBlock, + + /// Deep. + Deep, + + /// Unsupported card keyword. + #[serde(other)] + Unsupported, +} diff --git a/src/data/schema/mod.rs b/src/data/schema/mod.rs new file mode 100644 index 0000000..4f4be07 --- /dev/null +++ b/src/data/schema/mod.rs @@ -0,0 +1,19 @@ +//! This module defines the [Card] type and the types used in it to better describe attributes. + +mod card; +mod art; +mod r#type; +mod rarity; +mod region; +mod set; +mod speed; +mod keyword; + +pub use card::Card; +pub use art::CardArt; +pub use r#type::CardType; +pub use rarity::CardRarity; +pub use region::CardRegion; +pub use set::CardSet; +pub use speed::SpellSpeed; +pub use keyword::CardKeyword; diff --git a/src/data/schema/rarity.rs b/src/data/schema/rarity.rs new file mode 100644 index 0000000..8b3570f --- /dev/null +++ b/src/data/schema/rarity.rs @@ -0,0 +1,21 @@ +//! Module defining [CardRarity]. + +/// A possible card rarity. +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum CardRarity { + /// The card has no rarity, as it probably is not collectible. + #[serde(alias = "NONE")] + None, + /// A common card. + #[serde(alias = "COMMON")] + Common, + /// A rare card. + #[serde(alias = "RARE")] + Rare, + /// An epic card. + #[serde(alias = "EPIC")] + Epic, + /// A champion. + #[serde(alias = "CHAMPION")] + Champion, +} diff --git a/src/data/schema/region.rs b/src/data/schema/region.rs new file mode 100644 index 0000000..015d674 --- /dev/null +++ b/src/data/schema/region.rs @@ -0,0 +1,41 @@ +//! Module defining [CardRegion]. + +/// A region to which cards can belong to. +/// +/// Since more regions might be added in the future, especially Origin ones, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute). +#[non_exhaustive] +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum CardRegion { + /// Noxus. + Noxus, + /// Demacia. + Demacia, + /// Freljord. + Freljord, + /// Shadow Isles. + ShadowIsles, + /// Targon. + Targon, + /// Ionia. + Ionia, + /// Shurima. + Shurima, + /// Piltover & Zaun. + PiltoverZaun, + /// Bandle City. + BandleCity, + + /// Runeterra. + Runeterra, + + /// Origin: The Virtuoso. + Jhin, + /// Origin: Agony's Embrace. + Evelynn, + /// Origin: The Wandering Caretaker. + Bard, + + /// Unsupported region. + #[serde(other)] + Unsupported, +} diff --git a/src/data/schema/set.rs b/src/data/schema/set.rs new file mode 100644 index 0000000..301829e --- /dev/null +++ b/src/data/schema/set.rs @@ -0,0 +1,40 @@ +//! Module defining [CardSet]. + +/// The release set a [Card] may belong to. +/// +/// Since more sets will definitely be added in the future, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute). +#[non_exhaustive] +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum CardSet { + /// Foundations, or "base". + #[serde(rename = "Set1")] + Foundations, + + /// Rising Tides. + #[serde(rename = "Set2")] + RisingTides, + + /// Call of the Mountain. + #[serde(rename = "Set3")] + CallOfTheMountain, + + /// Empires of the Ascended. + #[serde(rename = "Set4")] + EmpiresOfTheAscended, + + /// Beyond the Bandlewood. + #[serde(rename = "Set5")] + BeyondTheBandlewood, + + /// Worldwalker. + #[serde(rename = "Set6")] + Worldwalker, + + /// Events, with cards released "outside" a set. + #[serde(rename = "SetEvent")] + Events, + + /// Unsupported card set. + #[serde(other)] + Unsupported, +} diff --git a/src/data/schema/speed.rs b/src/data/schema/speed.rs new file mode 100644 index 0000000..91dd3ef --- /dev/null +++ b/src/data/schema/speed.rs @@ -0,0 +1,15 @@ +//! Module defining [SpellSpeed]. + +/// A possible spell speed. +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum SpellSpeed { + /// Non-spell cards have this speed. + #[serde(alias = "")] + None, + /// A Slow spell. + Slow, + /// A Fast spell. + Fast, + /// Either a Burst or a Focus spell; to disambiguate between the two, check for the `Focus` keyword. + Burst, +} \ No newline at end of file diff --git a/src/data/schema/type.rs b/src/data/schema/type.rs new file mode 100644 index 0000000..c9e4d46 --- /dev/null +++ b/src/data/schema/type.rs @@ -0,0 +1,24 @@ +//! Module defining [Type]. + +/// A possible card type. +/// +/// Since more types might be added in the future, as it happened with landmarks, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute). +#[non_exhaustive] +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +pub enum CardType { + /// A spell. + Spell, + /// An unit: either a minion, or a champion. + /// Champions have their `supertype` set to `Champion`, and their `rarity` set to `Champion` as well. + Unit, + /// An ability triggered by an unit. + Ability, + /// A landmark. + Landmark, + /// A trap or boon. + Trap, + + /// Unsupported card type. + #[serde(other)] + Unsupported, +} \ No newline at end of file