Files
shinespark/src/menus/match_config.rs
T
EIREXE 1276562890
CI / build-and-test (push) Successful in 1m17s
CI / production-build (push) Successful in 9m37s
Rename pending match to match config and add match state (#51)
Reviewed-on: #51
Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
2026-09-20 11:13:15 +00:00

106 lines
2.8 KiB
Rust

use bevy::prelude::*;
use thiserror::Error;
use crate::{
fighter::FighterId,
match_loading::{MatchConfig, MatchPlayer, MatchRules},
stage::manifest::StageId,
};
pub struct MenuMatchPlayerSlot {
pub slot: usize,
pub fighter: Option<FighterId>,
}
#[derive(Resource, Default)]
pub struct MenuMatchConfig {
pub stage: Option<StageId>,
pub players: Vec<MenuMatchPlayerSlot>,
}
#[derive(Error, Debug, Reflect)]
pub enum MenuMatchConfigErrors {
#[error("Fighter slot {0} was invalid!")]
PlayerSlotInvalid(usize),
#[error("Invalid configuration: Slot {0} doesn't have a fighter selected")]
FighterNotSelectedForSlot(usize),
#[error("Invalid configuration: No stage selected")]
StageNotSelected,
}
impl MenuMatchConfig {
pub fn set_player_fighter(
&mut self,
player_slot: usize,
fighter_id: Option<FighterId>,
) -> Result<(), MenuMatchConfigErrors> {
let slot = self
.players
.get_mut(player_slot)
.ok_or(MenuMatchConfigErrors::PlayerSlotInvalid(player_slot))?;
slot.fighter = fighter_id;
Ok(())
}
pub fn get_player_fighter(
&self,
player_slot: usize,
) -> Result<Option<FighterId>, MenuMatchConfigErrors> {
let slot = self
.players
.get(player_slot)
.ok_or(MenuMatchConfigErrors::PlayerSlotInvalid(player_slot))?;
Ok(slot.fighter)
}
pub fn all_players_ready(&self) -> bool {
let has_unselected_fighter = self
.players
.iter()
.any(|player_slot| player_slot.fighter.is_none());
!has_unselected_fighter
}
pub fn to_match_config(&self) -> Result<MatchConfig, MenuMatchConfigErrors> {
let mut match_players = vec![];
let stage = self.stage.ok_or(MenuMatchConfigErrors::StageNotSelected)?;
for player in self.players.iter() {
let fighter_id =
player
.fighter
.ok_or(MenuMatchConfigErrors::FighterNotSelectedForSlot(
player.slot,
))?;
match_players.push(MatchPlayer {
fighter: fighter_id,
handle: player.slot,
});
}
Ok(MatchConfig {
players: match_players,
stage,
rules: MatchRules::default(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn menu_config_uses_default_match_rules() {
let menu = MenuMatchConfig {
stage: Some(StageId::TestStage),
players: vec![MenuMatchPlayerSlot {
slot: 0,
fighter: Some(FighterId::TestFighter),
}],
};
assert_eq!(menu.to_match_config().unwrap().rules, MatchRules::default());
}
}