A card game engine for TCGs, primarily Magic: The Gathering but with support for others
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Adding the first test card

+73 -12
+10
cards/test1.ron
··· 1 + Card( 2 + id: "86d0f2c0-3427-4b12-9267-052180544b47", 3 + name: "River Bear", 4 + cost: [ 5 + Green(2) 6 + ], 7 + attack: Some(2), 8 + defense: Some(2), 9 + text: "" 10 + )
+45 -3
src/game/card.rs
··· 1 + use std::str::FromStr; 2 + use serde::{Deserialize, de::Visitor}; 1 3 use uuid::Uuid; 2 4 use crate::game::{Result, player::PlayerId, state::GameState}; 3 5 4 6 pub struct CardId(Uuid); 5 7 pub struct CardDefId(Uuid); 6 8 9 + impl<'de> Deserialize<'de> for CardDefId { 10 + fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> 11 + where 12 + D: serde::Deserializer<'de> { 13 + 14 + struct UuidVisitor; 15 + 16 + impl<'de> Visitor<'de> for UuidVisitor { 17 + type Value = Uuid; 18 + 19 + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 20 + formatter.write_str("a uuid") 21 + } 22 + 23 + fn visit_string<E>(self, v: String) -> std::result::Result<Self::Value, E> 24 + where 25 + E: serde::de::Error, { 26 + match Uuid::from_str(&v) { 27 + Ok(id) => Ok(id.clone()), 28 + Err(err) => Err(E::custom(err.to_string())) 29 + } 30 + } 31 + } 32 + 33 + match deserializer.deserialize_string(UuidVisitor) { 34 + Ok(id) => Ok(CardDefId(id)), 35 + Err(err) => Err(err) 36 + } 37 + } 38 + } 39 + 40 + //pub trait Cost<'de>: Deserialize<'de> { 7 41 pub trait Cost { 8 42 fn can_pay(&self, state: &GameState, player: PlayerId, source: CardId) -> bool; 9 43 fn pay(&self, state: &mut GameState, player: PlayerId, source: CardId) -> Result<()>; ··· 11 45 12 46 pub trait Resource: Into<String> {} 13 47 48 + #[derive(Deserialize)] 14 49 pub enum MagicResource { 15 50 Black(i32), 16 51 White(i32), ··· 35 70 } 36 71 } 37 72 73 + #[derive(Deserialize)] 38 74 pub struct Card { 39 75 id: CardDefId, 40 76 name: String, 41 - cost: Box<dyn Cost> 77 + //cost: Box<dyn Cost> 78 + cost: MagicCost, 79 + attack: Option<i32>, 80 + defense: Option<i32>, 81 + text: String 42 82 } 43 83 44 84 pub struct CardInstance { 45 85 id: CardId, 46 - source: CardDefId 86 + source: CardDefId, 87 + current_attack: Option<i32>, 88 + current_defense: Option<i32> 47 89 } 48 90 49 - pub type MagicCost = MagicResource; 91 + pub type MagicCost = Vec<MagicResource>; 50 92 51 93 impl Cost for MagicCost { 52 94 fn can_pay(&self, state: &GameState, player: PlayerId, source: CardId) -> bool {
+10 -7
src/game/cards.rs
··· 7 7 #[include = "*.ron"] 8 8 struct Card; 9 9 10 - pub fn load_cards(namespace_uuid: &Uuid) -> Result<Vec<GameCard>> { 11 - let cards = Vec::<GameCard>::new(); 12 - 13 - for card in Card::iter() { 14 - let card_ron = ron::from_str::<Card>(&card.to_string())?; 10 + pub fn load_card(id: String, namespace_uuid: &Uuid) -> Result<Option<GameCard>> { 11 + let card_file = Card::get(&id); 12 + 13 + match card_file { 14 + Some(card) => { 15 + let card_str = String::from_utf8(card.data.to_vec())?; 16 + let card_data = ron::from_str::<GameCard>(&card_str)?; 17 + Ok(Some(card_data)) 18 + }, 19 + None => Ok(None) 15 20 } 16 - 17 - Ok(cards) 18 21 }
+8 -2
src/game/mod.rs
··· 1 - use std::{fmt, collections::HashMap}; 1 + use std::{collections::HashMap, fmt, string::FromUtf8Error}; 2 2 use crate::game::{state::GameState, card::{CardDefId, Card}}; 3 + use ron::de::SpannedError; 3 4 use uuid::Uuid; 4 - use ron::error::SpannedError; 5 5 6 6 pub mod card; 7 7 pub mod player; ··· 17 17 impl fmt::Display for ManaGroveError { 18 18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 19 19 write!(f, "Error in running game: {}", self.0) 20 + } 21 + } 22 + 23 + impl From<FromUtf8Error> for ManaGroveError { 24 + fn from(value: FromUtf8Error) -> Self { 25 + Self(value.to_string()) 20 26 } 21 27 } 22 28