diff --git a/Cargo.lock b/Cargo.lock index ee4f5e6..7621658 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1319,6 +1319,7 @@ dependencies = [ "bevy_egui", "noise", "paste", + "rand 0.8.5", "serde", ] diff --git a/crates/border-wars/Cargo.toml b/crates/border-wars/Cargo.toml index fabf283..68e7ebf 100644 --- a/crates/border-wars/Cargo.toml +++ b/crates/border-wars/Cargo.toml @@ -17,3 +17,4 @@ noise = "0.8.2" paste = "1.0.14" bevnet = { path = "../bevnet" } serde = "1.0.197" +rand = "0.8.5" diff --git a/crates/border-wars/src/map/generation.rs b/crates/border-wars/src/map/generation.rs index f1ce9ee..4f9088e 100644 --- a/crates/border-wars/src/map/generation.rs +++ b/crates/border-wars/src/map/generation.rs @@ -2,6 +2,7 @@ use bevy::prelude::*; use noise::{NoiseFn, Perlin}; +use serde::{Deserialize, Serialize}; use super::hex::*; use super::{Tile, TilePosition}; @@ -25,7 +26,7 @@ impl Plugin for MapGenerationPlugin { } /// An event to trigger the generation of the map. -#[derive(Event)] +#[derive(Event, Serialize, Deserialize, Clone, Copy)] pub struct StartMapGeneration { /// The seed used to generate the map. pub seed: u32, diff --git a/crates/border-wars/src/networking/mod.rs b/crates/border-wars/src/networking/mod.rs index 197eab5..9b31654 100644 --- a/crates/border-wars/src/networking/mod.rs +++ b/crates/border-wars/src/networking/mod.rs @@ -1,11 +1,13 @@ //! All the code related to the networking. -use bevnet::NetworkPlugin; +use bevnet::{NetworkAppExt, NetworkPlugin, Receive}; use bevy::prelude::*; use serde::{Deserialize, Serialize}; use self::check_connection::CheckConnectionPlugin; use self::connection::ConnectionPlugin; +use crate::map::generation::StartMapGeneration; +use crate::CurrentScene; pub mod check_connection; pub mod connection; @@ -17,6 +19,8 @@ impl Plugin for NetworkingPlugin { fn build(&self, app: &mut App) { app.add_plugins(NetworkPlugin::new("relay.cocosol.fr".to_string())) .add_plugins(ConnectionPlugin) + .add_systems(Update, handle_start_game) + .add_network_event::() .add_plugins(CheckConnectionPlugin); } } @@ -33,3 +37,19 @@ pub enum PlayerRank { /// The player. He can join the game and play. Player, } + +/// The event to start the game, that is send by the admin. +#[derive(Event, Serialize, Deserialize)] +pub struct StartGame(pub StartMapGeneration); + +/// A fonction that handle the start of the game. +fn handle_start_game( + mut next_stats: ResMut>, + mut start_game_events: EventReader>, + mut start_map_generation_writer: EventWriter, +) { + for event in start_game_events.read() { + next_stats.set(CurrentScene::Game); + start_map_generation_writer.send(event.1.0); + } +} diff --git a/crates/border-wars/src/scenes/lobby.rs b/crates/border-wars/src/scenes/lobby.rs index b734f2c..d3762cc 100644 --- a/crates/border-wars/src/scenes/lobby.rs +++ b/crates/border-wars/src/scenes/lobby.rs @@ -3,9 +3,11 @@ use bevnet::{Connection, SendTo}; use bevy::prelude::*; use bevy_egui::{egui, EguiContexts}; +use rand::Rng; +use crate::map::generation::StartMapGeneration; use crate::networking::connection::RemovePlayer; -use crate::networking::PlayerRank; +use crate::networking::{PlayerRank, StartGame}; use crate::{CurrentScene, Player}; /// The plugin for the lobby. @@ -20,10 +22,11 @@ impl Plugin for LobbyPlugin { /// Display the UI of the lobby. fn lobby_ui( mut ctx: EguiContexts, - mut next_scene: ResMut>, connection: Res, all_players_query: Query<&Player>, mut kick_player: EventWriter>, + mut map_size: Local, + mut start_game_event: EventWriter>, ) { // Get our player info. let Some(self_player) = all_players_query @@ -62,9 +65,44 @@ fn lobby_ui( ui.separator(); } - if self_player.rank == PlayerRank::Admin && ui.button("Run the game").clicked() { - next_scene.set(CurrentScene::Game); - // TODO: run the game + if self_player.rank != PlayerRank::Admin { + return; + } + + ui.add(egui::Slider::new(&mut (*map_size), 1..=5).text("map size")); + + if !ui.button("Run the game").clicked() { + return; + } + + let seed = rand::thread_rng().gen::(); + let index = *map_size as usize; + let nomber_of_players = all_players_query.iter().count() as u32; + + let radius = get_map_sizes(nomber_of_players)[index] as u16 * 2; + + // Start the game. + for player in all_players_query.iter() { + start_game_event.send(SendTo( + player.uuid, + StartGame(StartMapGeneration { seed, radius }), + )); } }); } + +/// Get the map sizes form a given number of players. +fn get_map_sizes(number_of_players: u32) -> Vec { + let mut result = Vec::with_capacity(6); + + let mut current = 0; + while result.len() < 6 { + current += 1; + + if (current * 6) % number_of_players == 0 { + result.push(current); + } + } + + result +}