Skip to content

Commit

Permalink
add in-game ping display
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksa2808 committed Dec 9, 2023
1 parent 07c63b7 commit 130deb4
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub struct HUDRoot;
#[derive(Component)]
pub struct GameTimerDisplay;

#[derive(Component)]
pub struct NetworkStatsDisplay;

#[derive(Component)]
pub struct PlayerPortraitDisplay;

Expand Down
9 changes: 5 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod web;
use bevy::{ecs as bevy_ecs, prelude::*};
use bevy_ggrs::prelude::*;

use types::Cooldown;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;

Expand Down Expand Up @@ -72,10 +73,10 @@ pub fn run() {
.init_resource::<HUDColors>()
.init_resource::<GameTextures>()
.add_state::<AppState>()
.insert_resource(NetworkStatsTimer(Timer::from_seconds(
2.0,
TimerMode::Repeating,
)))
.insert_resource(NetworkStatsCooldown {
cooldown: Cooldown::from_seconds(1.0),
print_cooldown: 0,
})
.add_systems(Update, print_network_stats_system)
.add_systems(
OnEnter(AppState::Lobby),
Expand Down
7 changes: 5 additions & 2 deletions src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ use rand::{rngs::StdRng, seq::IteratorRandom, Rng};
use crate::{
components::Position,
constants::COLORS,
types::{Direction, ICEServerConfig, PlayerID, PostFreezeAction},
types::{Cooldown, Direction, ICEServerConfig, PlayerID, PostFreezeAction},
};

#[derive(Resource)]
pub struct NetworkStatsTimer(pub Timer);
pub struct NetworkStatsCooldown {
pub cooldown: Cooldown,
pub print_cooldown: usize,
}

#[derive(Resource)]
pub struct Fonts {
Expand Down
45 changes: 40 additions & 5 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,54 @@ use crate::{

pub fn print_network_stats_system(
time: Res<Time>,
mut timer: ResMut<NetworkStatsTimer>,
mut network_stats_cooldown: ResMut<NetworkStatsCooldown>,
session: Option<Res<Session<GgrsConfig>>>,
mut network_stats_text_query: Query<&mut Text, With<NetworkStatsDisplay>>,
) {
if timer.0.tick(time.delta()).just_finished() {
let mut text = if let Ok(text) = network_stats_text_query.get_single_mut() {
text
} else {
network_stats_cooldown.cooldown.reset();
return;
};

network_stats_cooldown.cooldown.tick(time.delta());
if network_stats_cooldown.cooldown.trigger() {
let print_stats_to_console = if network_stats_cooldown.print_cooldown == 0 {
// print to console on every second update in order not to spam
network_stats_cooldown.print_cooldown = 1;
true
} else {
network_stats_cooldown.print_cooldown -= 1;
false
};

if let Some(sess) = session {
match sess.as_ref() {
Session::P2P(s) => {
let num_players = s.num_players();
for i in 0..num_players {
let mut player_pings = vec![None; num_players];
player_pings.iter_mut().enumerate().for_each(|(i, ping)| {
if let Ok(stats) = s.network_stats(i) {
info!("NetworkStats for player {}: {:?}", i, stats);
if print_stats_to_console {
info!("NetworkStats for player {}: {:?}", i, stats);
}
*ping = Some(stats.ping);
}
}
});
let stats_text = player_pings
.iter()
.enumerate()
.map(|(i, &p)| {
let ping = if let Some(p) = p {
p.to_string()
} else {
"-".to_string()
};
format!("{i}:{ping: >4}")
})
.join("\n");
text.sections[0].value = stats_text;
}
_ => unreachable!(),
}
Expand Down
85 changes: 84 additions & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use bevy::{prelude::Color, ui::BackgroundColor};
use std::time::Duration;

use bevy::{
prelude::Color,
time::{Timer, TimerMode},
ui::BackgroundColor,
};
use bevy_ggrs::ggrs::Config;
use bevy_matchbox::prelude::PeerId;
use bytemuck::{Pod, Zeroable};
Expand Down Expand Up @@ -64,3 +70,80 @@ pub enum PostFreezeAction {
ShowTournamentWinner { winner: PlayerID },
StartNewRound,
}

pub enum CooldownState {
Ready,
CoolingDown(Timer),
}

pub struct Cooldown {
state: CooldownState,
duration: Duration,
}

impl Cooldown {
pub fn from_seconds(duration: f32) -> Self {
Cooldown {
state: CooldownState::Ready,
duration: Duration::from_secs_f32(duration),
}
}

pub fn trigger(&mut self) -> bool {
if matches!(self.state, CooldownState::Ready) {
self.state = CooldownState::CoolingDown(Timer::from_seconds(
self.duration.as_secs_f32(),
TimerMode::Once,
));
true
} else {
false
}
}

pub fn tick(&mut self, delta: Duration) {
match self.state {
CooldownState::Ready => (),
CooldownState::CoolingDown(ref mut timer) => {
timer.tick(delta);
if timer.finished() {
self.state = CooldownState::Ready;
}
}
};
}

pub fn reset(&mut self) {
self.state = CooldownState::Ready;
}

#[allow(dead_code)]
pub fn duration(&self) -> Duration {
self.duration
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_cooldown() {
let mut cooldown = Cooldown::from_seconds(0.5);
assert_eq!(cooldown.duration(), Duration::from_millis(500));

assert!(cooldown.trigger());
assert!(!cooldown.trigger());

cooldown.tick(Duration::from_secs_f32(0.3));
assert!(!cooldown.trigger());

cooldown.tick(Duration::from_secs_f32(0.2));
assert!(cooldown.trigger());
assert!(!cooldown.trigger());

cooldown.reset();
assert!(cooldown.trigger());
assert!(!cooldown.trigger());
}
}
64 changes: 63 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rand::{rngs::StdRng, seq::IteratorRandom, Rng};
use crate::{
components::{
BombSatchel, BurningItem, Destructible, FullscreenMessageText, GameTimerDisplay, HUDRoot,
Item, LeaderboardUIContent, LeaderboardUIRoot, Player, PlayerPortrait,
Item, LeaderboardUIContent, LeaderboardUIRoot, NetworkStatsDisplay, Player, PlayerPortrait,
PlayerPortraitDisplay, Position, Solid, UIComponent, UIRoot, Wall,
},
constants::{
Expand Down Expand Up @@ -263,6 +263,68 @@ fn init_hud(
));
});

// network stats
parent
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
left: Val::Px(width - 6.0 * PIXEL_SCALE as f32),
top: Val::Px(0.0),
width: Val::Px(6.0 * PIXEL_SCALE as f32),
height: Val::Px(2.0 * ((1 + player_ids.len()) * PIXEL_SCALE) as f32),
..Default::default()
},
background_color: hud_colors.black_color.into(),
..Default::default()
},
UIComponent,
))
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_section(
"ping",
TextStyle {
font: fonts.mono.clone(),
font_size: 2.0 * PIXEL_SCALE as f32,
color: COLORS[15].into(),
},
),
style: Style {
position_type: PositionType::Absolute,
top: Val::Px(0.0),
left: Val::Px(PIXEL_SCALE as f32),
..Default::default()
},
..Default::default()
},
UIComponent,
));

parent.spawn((
TextBundle {
text: Text::from_section(
"",
TextStyle {
font: fonts.mono.clone(),
font_size: 2.0 * PIXEL_SCALE as f32,
color: COLORS[15].into(),
},
),
style: Style {
position_type: PositionType::Absolute,
top: Val::Px(2.0 * PIXEL_SCALE as f32),
left: Val::Px(0.0),
..Default::default()
},
..Default::default()
},
UIComponent,
NetworkStatsDisplay,
));
});

// player portraits
for &player_id in player_ids {
parent
Expand Down

0 comments on commit 130deb4

Please sign in to comment.