diff --git a/crates/border-wars/src/lib.rs b/crates/border-wars/src/lib.rs index 0b72f15..a97d7ec 100644 --- a/crates/border-wars/src/lib.rs +++ b/crates/border-wars/src/lib.rs @@ -2,8 +2,7 @@ use bevnet::Uuid; use bevy::prelude::*; -use bevy::utils::HashMap; -use networking::GameRank; +use networking::PlayerRank; use serde::{Deserialize, Serialize}; pub mod camera; @@ -27,15 +26,14 @@ pub enum CurrentScene { } /// A player in the game. -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Component, Resource)] pub struct Player { /// The name of the player. pub name: String, /// The rank of the player. - pub rank: GameRank, -} + pub rank: PlayerRank, -/// All the players in the game. -#[derive(Resource, Default)] -pub struct AllPlayers(pub HashMap); + /// The uuid of the player. + pub uuid: Uuid, +} diff --git a/crates/border-wars/src/networking/connection.rs b/crates/border-wars/src/networking/connection.rs index 3850d62..ee47512 100644 --- a/crates/border-wars/src/networking/connection.rs +++ b/crates/border-wars/src/networking/connection.rs @@ -1,11 +1,11 @@ //! All the code related to the connection. -use bevnet::{Connection, NetworkAppExt, Receive, SendTo, Uuid}; +use bevnet::{Connection, NetworkAppExt, Receive, SendTo}; use bevy::prelude::*; use serde::{Deserialize, Serialize}; -use super::GameRank; -use crate::{AllPlayers, CurrentScene, Player}; +use super::PlayerRank; +use crate::{CurrentScene, Player}; /// A plugin that manage connections (add, remove). pub struct ConnectionPlugin; @@ -15,7 +15,10 @@ impl Plugin for ConnectionPlugin { app.add_network_event::() .add_network_event::() .add_network_event::() - .add_systems(Update, (accept_connection, handle_change_player)); + .add_systems( + Update, + (accept_connection, handle_new_player, handle_remove_player), + ); } } @@ -25,32 +28,21 @@ pub struct RequestJoin(pub Player); /// An event that is trigger when a new player is added. #[derive(Event, Serialize, Deserialize)] -pub struct AddPlayer(Uuid, Player); +pub struct AddPlayer(Player); /// An event that is trigger when a player is removed. #[derive(Event, Serialize, Deserialize)] -pub struct RemovePlayer(pub Uuid); +pub struct RemovePlayer(pub Player); /// A fonction that accept new connection. /// It add the player to the list of all players. pub fn accept_connection( - all_players: Res, + all_players_query: Query<&Player>, mut requests_join_event: EventReader>, mut add_players_event: EventWriter>, - connection: Res, state: Res>, ) { - // Check if the player is an admin - if all_players - .get_by_connection(&connection) - .map(|player| player.rank == GameRank::Admin) - != Some(true) - { - return; - } - for request_join in requests_join_event.read() { - let new_uuid = request_join.0; let mut new_player = request_join.1.0.clone(); let current_state = *state.get(); @@ -58,42 +50,46 @@ pub fn accept_connection( if current_state == CurrentScene::Menu { return; } else if current_state == CurrentScene::Game { - new_player.rank = GameRank::Spectator; + new_player.rank = PlayerRank::Spectator; } - add_players_event.send(SendTo(new_uuid, AddPlayer(new_uuid, new_player.clone()))); + add_players_event.send(SendTo(new_player.uuid, AddPlayer(new_player.clone()))); - for (uuid, player) in all_players.0.iter() { + for old_player in all_players_query.iter() { // Link all players - add_players_event.send(SendTo(*uuid, AddPlayer(new_uuid, new_player.clone()))); - add_players_event.send(SendTo(new_uuid, AddPlayer(*uuid, player.clone()))); + add_players_event.send(SendTo(old_player.uuid, AddPlayer(new_player.clone()))); + add_players_event.send(SendTo(new_player.uuid, AddPlayer(old_player.clone()))); } } } -/// A fonction that handle new / remove players when a events. -pub fn handle_change_player( - mut add_players: EventReader>, +/// A fonction that handle new players when a events is received. +pub fn handle_new_player(mut add_players: EventReader>, mut commands: Commands) { + for add_player in add_players.read() { + commands.spawn(add_player.1.0.clone()); + } +} + +/// A fonction that handle remove players when a events is received. +pub fn handle_remove_player( mut remove_players: EventReader>, - mut all_players: ResMut, + mut commands: Commands, + all_players_query: Query<(Entity, &Player)>, connection: Res, mut next_scene: ResMut>, ) { - let Some(connection) = connection.identifier() else { - return; - }; - - for add_player in add_players.read() { - println!("{:?}", add_player.1.1); - all_players.0.insert(add_player.1.0, add_player.1.1.clone()); - } - for remove_player in remove_players.read() { - if remove_player.1.0 == connection { - all_players.0.clear(); + if Some(remove_player.1.0.uuid) == connection.identifier() { next_scene.set(CurrentScene::Menu); + all_players_query.iter().for_each(|(entity, _)| { + commands.entity(entity).despawn(); + }); return; } - all_players.0.remove(&remove_player.1.0); + for (entity, player) in all_players_query.iter() { + if remove_player.1.0.uuid == player.uuid { + commands.entity(entity).despawn(); + } + } } } diff --git a/crates/border-wars/src/networking/mod.rs b/crates/border-wars/src/networking/mod.rs index 2983659..e3f4f8a 100644 --- a/crates/border-wars/src/networking/mod.rs +++ b/crates/border-wars/src/networking/mod.rs @@ -1,11 +1,10 @@ //! All the code related to the networking. -use bevnet::{Connection, NetworkPlugin}; +use bevnet::NetworkPlugin; use bevy::prelude::*; use serde::{Deserialize, Serialize}; use self::connection::ConnectionPlugin; -use crate::{AllPlayers, Player}; pub mod connection; @@ -15,28 +14,19 @@ pub struct NetworkingPlugin; impl Plugin for NetworkingPlugin { fn build(&self, app: &mut App) { app.add_plugins(NetworkPlugin::new("relay.cocosol.fr".to_string())) - .add_plugins(ConnectionPlugin) - .init_resource::(); + .add_plugins(ConnectionPlugin); } } /// The rank of the player. #[derive(PartialEq, Eq, Serialize, Deserialize, Clone, Copy, Debug)] -pub enum GameRank { - /// The player is a spectator. He does not play the game. +pub enum PlayerRank { + /// A spectator. He does not play the game, just renderer the game. Spectator, - /// The player is an admin. He can remove players. + /// An admin. He manages the game and play the game. Admin, - /// The player is a player. He can join the game and play. + /// The player. He can join the game and play. Player, } - -impl AllPlayers { - /// Get the player by a connection. - pub fn get_by_connection(&self, connection: &Connection) -> Option<&Player> { - let uuid = connection.identifier()?; - self.0.get(&uuid) - } -} diff --git a/crates/border-wars/src/scenes/lobby.rs b/crates/border-wars/src/scenes/lobby.rs index 840ac6e..89201c9 100644 --- a/crates/border-wars/src/scenes/lobby.rs +++ b/crates/border-wars/src/scenes/lobby.rs @@ -5,8 +5,8 @@ use bevy::prelude::*; use bevy_egui::{egui, EguiContexts}; use crate::networking::connection::RemovePlayer; -use crate::networking::GameRank; -use crate::{AllPlayers, CurrentScene}; +use crate::networking::PlayerRank; +use crate::{CurrentScene, Player}; /// The plugin for the lobby. pub struct LobbyPlugin; @@ -22,9 +22,17 @@ fn lobby_ui( mut ctx: EguiContexts, mut next_scene: ResMut>, connection: Res, - all_players: Res, + all_players_query: Query<&Player>, mut kick_player: EventWriter>, ) { + // Get our player info. + let Some(self_player) = all_players_query + .iter() + .find(|player| connection.identifier() == Some(player.uuid)) + else { + return; + }; + egui::CentralPanel::default().show(ctx.ctx_mut(), |ui| { ui.heading("Border Wars"); @@ -32,7 +40,7 @@ fn lobby_ui( ui.label("Game created"); ui.horizontal(|ui| { - if all_players.get_by_connection(&connection).map(|p| p.rank) != Some(GameRank::Admin) { + if self_player.rank != PlayerRank::Admin { return; } ui.label("Game ID: "); @@ -42,22 +50,20 @@ fn lobby_ui( ui.separator(); - for (connected_player_id, connected_player) in all_players.0.iter() { - ui.label(connected_player.name.to_string()); - if all_players.get_by_connection(&connection).map(|p| p.rank) == Some(GameRank::Admin) - && connected_player.rank != GameRank::Admin + for player in all_players_query.iter() { + ui.label(player.name.to_string()); + if self_player.rank == PlayerRank::Admin + && player.rank != PlayerRank::Admin && ui.button("Remove").clicked() { - for sender_id in all_players.0.keys() { - kick_player.send(SendTo(*sender_id, RemovePlayer(*connected_player_id))); + for sender_id in all_players_query.iter() { + kick_player.send(SendTo(sender_id.uuid, RemovePlayer(player.clone()))); } } ui.separator(); } - if all_players.get_by_connection(&connection).map(|p| p.rank) == Some(GameRank::Admin) - && ui.button("Run the game").clicked() - { + if self_player.rank == PlayerRank::Admin && ui.button("Run the game").clicked() { next_scene.set(CurrentScene::Game); // TODO: run the game } diff --git a/crates/border-wars/src/scenes/menu.rs b/crates/border-wars/src/scenes/menu.rs index fe16511..39a2239 100644 --- a/crates/border-wars/src/scenes/menu.rs +++ b/crates/border-wars/src/scenes/menu.rs @@ -5,8 +5,8 @@ use bevy::prelude::*; use bevy_egui::{egui, EguiContexts}; use crate::networking::connection::RequestJoin; -use crate::networking::GameRank; -use crate::{AllPlayers, CurrentScene, Player}; +use crate::networking::PlayerRank; +use crate::{CurrentScene, Player}; /// The plugin for the menu. pub struct MenuPlugin; @@ -16,6 +16,7 @@ impl Plugin for MenuPlugin { app.add_systems(Update, menu_ui.run_if(in_state(CurrentScene::Menu))); } } + /// Display the UI of the menu to host a game or join one. fn menu_ui( mut ctx: EguiContexts, @@ -23,8 +24,8 @@ fn menu_ui( mut next_scene: ResMut>, mut request_join: EventWriter>, mut name: Local, - mut all_player: ResMut, connection: Res, + mut commands: Commands, ) { let Some(uuid) = connection.identifier() else { return; @@ -55,7 +56,8 @@ fn menu_ui( game_id, RequestJoin(Player { name: name.clone(), - rank: GameRank::Player, + rank: PlayerRank::Player, + uuid, }), )); } @@ -65,13 +67,11 @@ fn menu_ui( if ui.button("Create new game").clicked() { next_scene.set(CurrentScene::Lobby); - all_player.0.insert( + commands.spawn(Player { + name: name.clone(), + rank: PlayerRank::Admin, uuid, - Player { - name: name.clone(), - rank: GameRank::Admin, - }, - ); + }); } }); } diff --git a/crates/relay-client/src/lib.rs b/crates/relay-client/src/lib.rs index b052784..b390d21 100644 --- a/crates/relay-client/src/lib.rs +++ b/crates/relay-client/src/lib.rs @@ -80,7 +80,7 @@ impl Connection { path.push(".relay-data"); // Check if the file exists. - match path.exists() { + match false { true => { // Read the file and parse the identifier and secret key. let contents = fs::read(&path)?;