DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

fa602b0635a2bf7ad8a0894c736a0b878fd5941f — Jonni Liljamo 1 year, 4 months ago 13a40ec
feat(client): something something something
M client/src/api/game/mod.rs => client/src/api/game/mod.rs +14 -0
@@ 70,6 70,20 @@ pub enum Command {
        amount: usize,
        sides: usize,
    },
    GivePlays {
        amount: usize,
    },
    GiveBuys {
        amount: usize,
    },
    GiveVP {
        amount: usize,
    },
    /// mark a card in the targets deck to be trashed on play.
    /// if index in None, a random card will be chosen
    MarkCardInDeckToBeTrashed {
        index: Option<usize>,
    },
}

#[derive(Deserialize, Serialize, Clone, PartialEq)]

M client/src/game_status/mod.rs => client/src/game_status/mod.rs +4 -0
@@ 17,6 17,8 @@ mod parser;
#[derive(Deserialize, Serialize, Clone, PartialEq)]
pub struct CardAction {
    pub command: Command,
    /// if false, targets the next player
    pub target_self: bool,
}

#[derive(Deserialize, Serialize, Clone, PartialEq)]


@@ 30,6 32,8 @@ pub struct Card {
    /// if set, use this?
    //vp_cost: Option<u32>,
    pub actions: Vec<CardAction>,
    /// trash after play?
    pub to_be_trashed: bool,
}

/// a supply pile holds an amount of some card

M client/src/game_status/parser.rs => client/src/game_status/parser.rs +58 -16
@@ 19,14 19,11 @@ use crate::{
use super::{GameStatus, PlayerState, PlayerStatus};

/// funny unsafe wrapper
fn get_invoker_target<'a, K, V>(
    players: &'a mut HashMap<K, V>,
    invoker: &K,
    target: &K,
) -> (&'a mut V, &'a mut V)
where
    K: Eq + std::hash::Hash,
{
fn get_invoker_target_next<'a>(
    players: &'a mut HashMap<String, PlayerStatus>,
    invoker: &String,
    target: &String,
) -> (&'a mut PlayerStatus, &'a mut PlayerStatus, String) {
    unsafe {
        // NOTE: soo... I don't really know the consequences of possibly
        // having two mutable references to the same value, but I guess


@@ 36,9 33,22 @@ where
        // if the wanted values were the same.
        // e.g. returning (V, None), if the keys were the same.

        let invoker_ref = players.get_mut(invoker).unwrap() as *mut _;
        let target_ref = players.get_mut(target).unwrap() as *mut _;
        (&mut *invoker_ref, &mut *target_ref)
        let invoker_ref: *mut PlayerStatus = players.get_mut(invoker).unwrap() as *mut _;
        let target_ref: *mut PlayerStatus = players.get_mut(target).unwrap() as *mut _;

        let next_turn_n: usize = if ((*invoker_ref).turn_n + 1) > (players.len() - 1)
        {
            0
        } else {
            (*invoker_ref).turn_n + 1
        };

        let next_player = players
            .iter()
            .find(|np| np.1.turn_n == next_turn_n)
            .unwrap();

        (&mut *invoker_ref, &mut *target_ref, next_player.0.clone())
    }
}



@@ 86,6 96,9 @@ pub fn parse(game: &Game) -> Result<GameStatus, ()> {
        parse_action(&action, game, &mut game_status);
    }

    // TODO: check for end conditions, declare one player as winner.
    // update game state in API to ended, set ended date (in API).

    Ok(game_status)
}



@@ 100,8 113,8 @@ fn parse_action(action: &Action, game: &Game, game_status: &mut GameStatus) {

    // invoker: the one who invoked the action
    // target: the one who the action affects, may also be the invoker, e.g. draw
    let (invoker, target) =
        get_invoker_target(&mut game_status.players, &action.invoker, &action.target);
    let (invoker, target, next_player_uuid) =
        get_invoker_target_next(&mut game_status.players, &action.invoker, &action.target);

    let Some(action_pos) = game_status.actions.iter().position(|a| *a == action.clone()) else {
        panic!("Action was not found in game_status.actions!");


@@ 148,13 161,22 @@ fn parse_action(action: &Action, game: &Game, game_status: &mut GameStatus) {
            target.plays -= 1;

            let card = target.hand.remove(*index);
            target.discard.push(card.clone());
            if card.to_be_trashed {
                // marked for trash, let it fall into oblivion
            } else {
                // discard normally
                target.discard.push(card.clone());
            }

            for card_action in &card.actions {
                let action = &Action::new(
                    &game.id,
                    &action.invoker,
                    &action.target,
                    if card_action.target_self {
                        &action.invoker
                    } else {
                        &next_player_uuid
                    },
                    &card_action.command,
                    current_seed!(action),
                );


@@ 218,7 240,7 @@ fn parse_action(action: &Action, game: &Game, game_status: &mut GameStatus) {
                &game.id,
                &action.target,
                &action.target,
                &Command::Draw { amount: 4 },
                &Command::Draw { amount: 2 },
                current_seed!(action),
            );
            game_status


@@ 236,6 258,26 @@ fn parse_action(action: &Action, game: &Game, game_status: &mut GameStatus) {
                    Rng::with_seed(action.seed.parse::<u64>().unwrap()).usize(1..=*sides);
            }
        }
        Command::GivePlays { amount } => {
            target.plays += amount;
        }
        Command::GiveBuys { amount } => {
            target.buys += amount;
        }
        Command::GiveVP { amount } => {
            target.vp += amount;
        }
        Command::MarkCardInDeckToBeTrashed { index } => {
            match index {
                Some(index) => {
                    target.deck.get_mut(*index).unwrap().to_be_trashed = true;
                }
                None => {
                    let deck_len = target.deck.len();
                    target.deck.get_mut(Rng::with_seed(action.seed.parse::<u64>().unwrap()).usize(0..deck_len)).unwrap().to_be_trashed = true;
                }
            }
        }
        #[allow(unreachable_patterns)]
        _ => todo!(),
    }

M client/src/plugins/game/card/mod.rs => client/src/plugins/game/card/mod.rs +1 -0
@@ 56,6 56,7 @@ impl Default for VisualCard {
                long_details: vec![],
                cost: 0,
                actions: vec![],
                to_be_trashed: false,
            },
        }
    }

M client/src/plugins/game/ui/state_button.rs => client/src/plugins/game/ui/state_button.rs +3 -14
@@ 12,7 12,7 @@ use crate::{
    api::game::{Action, Command},
    game_status::PlayerState,
    plugins::{GameActionCreateCallEvent, GameData},
    AppState, Global,
    AppState, Global, util::get_next_player,
};

pub struct StateButtonPlugin;


@@ 162,24 162,13 @@ fn interact_state_button(
                        });
                    }
                    PlayerState::BuyPhase => {
                        let next_turn_n: usize = if (player.turn_n + 1) > (status.players.len() - 1)
                        {
                            0
                        } else {
                            player.turn_n + 1
                        };

                        let next_player = status
                            .players
                            .iter()
                            .find(|np| np.1.turn_n == next_turn_n)
                            .unwrap();
                        let next_player = get_next_player(player, &status);

                        gac_ev_w.send(GameActionCreateCallEvent {
                            action: Action::new(
                                &game.id,
                                &user.id,
                                next_player.0,
                                &next_player.0,
                                &Command::EndTurn {},
                                None,
                            ),

M client/src/util/mod.rs => client/src/util/mod.rs +17 -0
@@ 10,3 10,20 @@ pub mod egui;

mod action_to_log;
pub use action_to_log::action_to_log;

use crate::game_status::{GameStatus, PlayerStatus};

pub fn get_next_player<'a>(player: &'a PlayerStatus, game_status: &'a GameStatus) -> (&'a String, &'a PlayerStatus) {
    let next_turn_n: usize = if (player.turn_n + 1) > (game_status.players.len() - 1)
    {
        0
    } else {
        player.turn_n + 1
    };

    game_status
        .players
        .iter()
        .find(|np| np.1.turn_n == next_turn_n)
        .unwrap()
}