Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Prevent pausing in online from timing out network, allow game to continue running #1003

Merged
merged 5 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
pub input_collector: PlayerInputCollector,
pub accumulator: f64,
pub last_run: Option<Instant>,
/// Disables local input for session.
disable_local_input: bool,
}

impl SessionRunner for JumpyDefaultMatchRunner {
Expand Down Expand Up @@ -153,7 +155,13 @@
let Some(source) = &player_input.control_source else {
return;
};
player_input.control = *input.get(source).unwrap();
if !self.disable_local_input {
player_input.control = *input.get(source).unwrap();
} else {
// This runner is only used for offline play, use default control for all to
// disable input by using default (no input).
player_input.control = PlayerControl::default();
}
});
}

Expand Down Expand Up @@ -190,4 +198,8 @@
fn restart_session(&mut self) {
*self = JumpyDefaultMatchRunner::default();
}

fn disable_local_input(&mut self, disable_input: bool) {

Check failure on line 202 in src/core.rs

View workflow job for this annotation

GitHub Actions / 🔧 Clippy correctness checks (x86_64-unknown-linux-gnu, target)

method `disable_local_input` is not a member of trait `SessionRunner`

Check failure on line 202 in src/core.rs

View workflow job for this annotation

GitHub Actions / 🔧 Clippy correctness checks (wasm32-unknown-unknown, web-target)

method `disable_local_input` is not a member of trait `SessionRunner`
self.disable_local_input = disable_input;
}
}
75 changes: 42 additions & 33 deletions src/ui/pause_menu.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::ops::Deref;

#[cfg(not(target_arch = "wasm32"))]
use bones_framework::networking::NetworkMatchSocket;

use crate::{core::JumpyDefaultMatchRunner, prelude::*};

use super::scoring::ScoringMenuState;
Expand Down Expand Up @@ -32,15 +29,7 @@
world: &World,
assets: Res<AssetServer>,
mut pause_menu: ResMutInit<PauseMenu>,

#[cfg(not(target_arch = "wasm32"))] socket: Option<Res<NetworkMatchSocket>>,
) {
// TODO allow pause menu in online game
#[cfg(not(target_arch = "wasm32"))]
if socket.is_some() {
return;
}

let mut back_to_menu = false;
let mut restart_game = false;
let mut close_pause_menu = false;
Expand All @@ -49,7 +38,12 @@
if let Some(session) = sessions.get_mut(SessionNames::GAME) {
let pause_pressed = controls.values().any(|x| x.pause_just_pressed);

if !session.active && pause_menu.menu_open {
#[cfg(not(target_arch = "wasm32"))]
let is_online = session.world.get_resource::<NetworkInfo>().is_some();
#[cfg(target_arch = "wasm32")]
let is_online = false;

if pause_menu.menu_open {
let page = ctx.get_state::<PauseMenuPage>();

match page {
Expand Down Expand Up @@ -80,6 +74,7 @@
&mut restart_game,
&mut back_to_menu,
&mut close_pause_menu,
is_online,
),
);
});
Expand Down Expand Up @@ -110,9 +105,15 @@
});
}
}

// When pause menu is open (and not about to be closed), we -re-pause every frame regardless of if just pressed
// because in online, if menu is open during a map transition, we need to make sure new net session
// disables input to re-pause itself.
if !close_pause_menu {
pause_session(true, is_online, session, false);
}
} else if pause_pressed {
pause_menu.menu_open = true;
session.active = false;
}
}

Expand Down Expand Up @@ -155,30 +156,27 @@
}

fn main_pause_menu(
mut param: In<(&mut egui::Ui, &mut Session, &mut bool, &mut bool, &mut bool)>,
mut param: In<(
&mut egui::Ui,
&mut Session,
&mut bool,
&mut bool,
&mut bool,
bool,
)>,
meta: Root<GameMeta>,
localization: Localization<GameMeta>,
controls: Res<GlobalPlayerControls>,
scoring_menu: Res<ScoringMenuState>,

#[cfg(not(target_arch = "wasm32"))] socket: Option<Res<NetworkMatchSocket>>,
) {
let (ui, session, restart_game, back_to_menu, close_pause_menu) = &mut *param;

#[cfg(not(target_arch = "wasm32"))]
let is_online = socket.is_some();
#[cfg(target_arch = "wasm32")]
let is_online = false;
let (ui, session, restart_game, back_to_menu, close_pause_menu, is_online) = &mut *param;

// Unpause the game
if controls.values().any(|x| x.pause_just_pressed) {
if !scoring_menu.active {
// Do not unpause game session if scoring menu open.
// TODO: Use some kind of pause stack to track what different systems
// might want session to remain inactive.
session.active = true;
}

// Do not unpause game session if scoring menu open.
// TODO: Use some kind of pause stack to track what different systems
// might want session to remain inactive.
pause_session(false, *is_online, session, scoring_menu.active);
**close_pause_menu = true;
}

Expand Down Expand Up @@ -213,14 +211,12 @@
.focus_by_default(ui)
.clicked()
{
session.active = true;
pause_session(false, *is_online, session, false);
**close_pause_menu = true;
}

// Local game buttons
ui.scope(|ui| {
ui.set_enabled(!is_online);

// Map select button
if BorderedButton::themed(
&meta.theme.buttons.normal,
Expand Down Expand Up @@ -260,7 +256,7 @@
.clicked()
{
// TODO: show editor.
session.active = true;
pause_session(false, *is_online, session, false);
**close_pause_menu = true;
}
});
Expand All @@ -275,3 +271,16 @@
}
});
}

/// Helper for pausing session depending on if online or offline match.
/// `remain_inactive` is used if other systems like scoring have set session inactive and wish to
/// prevent that change.
fn pause_session(paused: bool, is_online: bool, session: &mut Session, remain_inactive: bool) {
if is_online {
// Online session remains active so that it will not timeout with other players.
// Instead we disable the input so it is not captured by game while paused.
session.runner.disable_local_input(paused);

Check failure on line 282 in src/ui/pause_menu.rs

View workflow job for this annotation

GitHub Actions / 🔧 Clippy correctness checks (x86_64-unknown-linux-gnu, target)

no method named `disable_local_input` found for struct `std::boxed::Box<(dyn bones_framework::prelude::SessionRunner + 'static)>` in the current scope

Check failure on line 282 in src/ui/pause_menu.rs

View workflow job for this annotation

GitHub Actions / 🔧 Clippy correctness checks (wasm32-unknown-unknown, web-target)

no method named `disable_local_input` found for struct `std::boxed::Box<(dyn bones_framework::prelude::SessionRunner + 'static)>` in the current scope
} else if !paused && !remain_inactive {
session.active = !paused;
}
}
Loading