Merge branch 'main' into start-game
All checks were successful
Rust Checks / checks (pull_request) Successful in 2m43s
Rust Checks / checks (push) Successful in 3m1s

This commit is contained in:
CoCo_Sol 2024-03-30 19:48:42 +01:00
commit 0b5aa1d90e
4 changed files with 124 additions and 4 deletions

View file

@ -26,7 +26,7 @@ pub enum CurrentScene {
}
/// A player in the game.
#[derive(Serialize, Deserialize, Clone, Debug, Component, Resource)]
#[derive(Serialize, Deserialize, Clone, Debug, Component, Resource, PartialEq, Eq, Hash)]
pub struct Player {
/// The name of the player.
pub name: String,

View file

@ -0,0 +1,118 @@
//! All the code related to the check connection (check every X seconds if any
//! player is still connected).
use std::time::Instant;
use bevnet::{Connection, NetworkAppExt, Receive, SendTo};
use bevy::prelude::*;
use bevy::utils::HashMap;
use serde::{Deserialize, Serialize};
use crate::Player;
/// A plugin that check if a player is still connected.
pub struct CheckConnectionPlugin;
/// An event that is trigger when a player is disconnected.
#[derive(Event)]
pub struct PlayerDisconnected(pub Player);
/// An event that is send between all players to check if a player is still
/// connected.
#[derive(Event, Serialize, Deserialize)]
struct IAmConnected(Player);
impl Plugin for CheckConnectionPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
(
check_connection,
send_check_connection,
handle_disconnect_player,
),
)
.add_event::<PlayerDisconnected>()
.add_network_event::<IAmConnected>();
}
}
/// The interval to check if a player is still connected.
/// We put this into a const because we don't want to change it.
const CHECK_CONNECTION_INTERVAL: std::time::Duration = std::time::Duration::from_secs(5);
/// A fonction that check if a player is still connected.
fn check_connection(
all_players_query: Query<&Player>,
mut disconnect_event: EventWriter<PlayerDisconnected>,
mut checked_players: Local<HashMap<Player, Instant>>,
mut connect_event: EventReader<Receive<IAmConnected>>,
) {
for Receive(_, IAmConnected(player)) in connect_event.read() {
checked_players.insert(player.clone(), Instant::now());
}
for player in all_players_query.iter() {
if !(*checked_players).contains_key(player) {
checked_players.insert(player.clone(), Instant::now());
}
let Some(last_seen) = (*checked_players).get_mut(player) else {
continue;
};
if last_seen.elapsed() > CHECK_CONNECTION_INTERVAL {
disconnect_event.send(PlayerDisconnected(player.clone()));
checked_players.remove(player);
}
}
}
/// A simple time/instant that implement Default.
struct Time(std::time::Instant);
impl Default for Time {
fn default() -> Self {
Self(std::time::Instant::now())
}
}
/// A fonction that send a check connection event to all players.
fn send_check_connection(
mut check_connection_event: EventWriter<SendTo<IAmConnected>>,
all_players_query: Query<&Player>,
connection: Res<Connection>,
mut timer: Local<Time>,
) {
if timer.0.elapsed() < CHECK_CONNECTION_INTERVAL / 2 {
return;
}
let Some(self_player) = all_players_query
.iter()
.find(|player| connection.identifier() == Some(player.uuid))
else {
return;
};
for player in all_players_query.iter() {
check_connection_event.send(SendTo(player.uuid, IAmConnected(self_player.clone())));
}
timer.0 = std::time::Instant::now();
}
/// A fonction that handle player disconnection.
fn handle_disconnect_player(
mut disconnect_players: EventReader<PlayerDisconnected>,
all_players_query: Query<(&Player, Entity)>,
mut commands: Commands,
) {
for PlayerDisconnected(disconnect_player) in disconnect_players.read() {
let Some((_, entity)) = all_players_query
.iter()
.find(|(player, _entity)| *player == disconnect_player)
else {
continue;
};
commands.entity(entity).despawn();
}
}

View file

@ -4,10 +4,12 @@ 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;
/// The plugin for the networking.
@ -18,12 +20,13 @@ impl Plugin for NetworkingPlugin {
app.add_plugins(NetworkPlugin::new("relay.cocosol.fr".to_string()))
.add_plugins(ConnectionPlugin)
.add_systems(Update, start_game)
.add_network_event::<StartGame>();
.add_network_event::<StartGame>()
.add_plugins(CheckConnectionPlugin);
}
}
/// The rank of the player.
#[derive(PartialEq, Eq, Serialize, Deserialize, Clone, Copy, Debug)]
#[derive(PartialEq, Eq, Serialize, Deserialize, Clone, Copy, Debug, Hash)]
pub enum PlayerRank {
/// A spectator. He does not play the game, just renderer the game.
Spectator,

View file

@ -46,7 +46,6 @@ fn lobby_ui(
return;
}
ui.label("Game ID: ");
// TODO : get the game ID and display it.
ui.text_edit_singleline(&mut connection.identifier().unwrap_or_default().to_string());
});