Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c68e1fb55 |
+3
-59
@@ -1,14 +1,9 @@
|
|||||||
//! Rollback-simulated state for an active match.
|
//! Rollback-simulated state for an active match.
|
||||||
|
|
||||||
use bevy::input::InputSystems;
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_ggrs::{RunGgrsSystems, prelude::*};
|
use bevy_ggrs::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::match_loading::{MatchConfig, MatchRules};
|
||||||
AppState,
|
|
||||||
match_loading::{MatchConfig, MatchRules},
|
|
||||||
netcode::session::SessionConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Resource, Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Resource, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct MatchState {
|
pub struct MatchState {
|
||||||
@@ -24,11 +19,6 @@ pub struct PlayerMatchState {
|
|||||||
pub deaths: u32,
|
pub deaths: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct PauseState {
|
|
||||||
pub paused: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MatchState {
|
impl MatchState {
|
||||||
pub fn from_config(config: &MatchConfig) -> Self {
|
pub fn from_config(config: &MatchConfig) -> Self {
|
||||||
let stocks_remaining = match &config.rules {
|
let stocks_remaining = match &config.rules {
|
||||||
@@ -56,56 +46,10 @@ pub struct MatchRuntimePlugin;
|
|||||||
impl Plugin for MatchRuntimePlugin {
|
impl Plugin for MatchRuntimePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.rollback_resource_with_clone::<MatchState>()
|
app.rollback_resource_with_clone::<MatchState>()
|
||||||
.checksum_resource_with_hash::<MatchState>()
|
.checksum_resource_with_hash::<MatchState>();
|
||||||
.init_resource::<PauseState>()
|
|
||||||
.configure_sets(PreUpdate, RunGgrsSystems.run_if(ggrs_should_run))
|
|
||||||
.add_systems(OnEnter(AppState::InMatch), reset_pause)
|
|
||||||
.add_systems(OnExit(AppState::InMatch), reset_pause)
|
|
||||||
.add_systems(
|
|
||||||
PreUpdate,
|
|
||||||
toggle_pause
|
|
||||||
.after(InputSystems)
|
|
||||||
.before(RunGgrsSystems)
|
|
||||||
.run_if(in_state(AppState::InMatch)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ggrs_should_run(pause: Option<Res<PauseState>>) -> bool {
|
|
||||||
!pause.is_some_and(|pause| pause.paused)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn toggle_pause(
|
|
||||||
key: Res<ButtonInput<KeyCode>>,
|
|
||||||
gamepads: Query<&Gamepad>,
|
|
||||||
session: Res<SessionConfig>,
|
|
||||||
mut pause: ResMut<PauseState>,
|
|
||||||
mut virtual_time: ResMut<Time<Virtual>>,
|
|
||||||
) {
|
|
||||||
if session.is_multiplayer() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pressed = key.just_pressed(KeyCode::Escape)
|
|
||||||
|| gamepads
|
|
||||||
.iter()
|
|
||||||
.any(|gamepad| gamepad.just_pressed(GamepadButton::Start));
|
|
||||||
if !pressed {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pause.paused = !pause.paused;
|
|
||||||
virtual_time.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset_pause(
|
|
||||||
mut pause: ResMut<PauseState>,
|
|
||||||
mut virtual_time: ResMut<Time<Virtual>>,
|
|
||||||
) {
|
|
||||||
pause.paused = false;
|
|
||||||
virtual_time.unpause();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
+1
-1
@@ -226,7 +226,7 @@ fn gamepad_input(
|
|||||||
input.accept.accumulate(&status);
|
input.accept.accumulate(&status);
|
||||||
}
|
}
|
||||||
MenuInputMapAction::Start => {
|
MenuInputMapAction::Start => {
|
||||||
input.start.accumulate(&status);
|
input.accept.accumulate(&status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,15 +42,6 @@ pub enum SessionConfigError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SessionConfig {
|
impl SessionConfig {
|
||||||
/// Returns whether this match has more than one remote participant.
|
|
||||||
pub fn is_multiplayer(&self) -> bool {
|
|
||||||
self.players.len() > 1
|
|
||||||
|| self
|
|
||||||
.players
|
|
||||||
.iter()
|
|
||||||
.any(|player| matches!(player, PlayerConnection::Remote(_)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_args(args: &Args, player_count: usize) -> Result<Self, SessionConfigError> {
|
pub fn from_args(args: &Args, player_count: usize) -> Result<Self, SessionConfigError> {
|
||||||
if player_count == 0 {
|
if player_count == 0 {
|
||||||
return Err(SessionConfigError::NoPlayers);
|
return Err(SessionConfigError::NoPlayers);
|
||||||
@@ -205,13 +196,6 @@ mod tests {
|
|||||||
config.players,
|
config.players,
|
||||||
[PlayerConnection::Local, PlayerConnection::Local]
|
[PlayerConnection::Local, PlayerConnection::Local]
|
||||||
);
|
);
|
||||||
assert!(config.is_multiplayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn single_local_player_is_not_multiplayer() {
|
|
||||||
let config = SessionConfig::from_args(&args(&["game", "--players", "1"]), 1).unwrap();
|
|
||||||
assert!(!config.is_multiplayer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -223,7 +207,6 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(config.players[0], PlayerConnection::Local));
|
assert!(matches!(config.players[0], PlayerConnection::Local));
|
||||||
assert!(matches!(config.players[1], PlayerConnection::Remote(_)));
|
assert!(matches!(config.players[1], PlayerConnection::Remote(_)));
|
||||||
assert!(config.is_multiplayer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+2
-53
@@ -3,7 +3,7 @@ use bevy::prelude::*;
|
|||||||
use crate::{
|
use crate::{
|
||||||
AppState,
|
AppState,
|
||||||
match_loading::{MatchConfig, MatchRules},
|
match_loading::{MatchConfig, MatchRules},
|
||||||
match_runtime::{MatchState, PauseState},
|
match_runtime::MatchState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod battle_ui;
|
pub mod battle_ui;
|
||||||
@@ -11,9 +11,6 @@ pub mod errors;
|
|||||||
pub mod fighter_info;
|
pub mod fighter_info;
|
||||||
pub mod stock_icon;
|
pub mod stock_icon;
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct PauseOverlay;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct InGameUIPlugin;
|
pub struct InGameUIPlugin;
|
||||||
|
|
||||||
@@ -35,54 +32,6 @@ impl Plugin for InGameUIPlugin {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
.add_systems(Update, sync_pause_overlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sync_pause_overlay(
|
|
||||||
pause: Res<PauseState>,
|
|
||||||
overlay: Query<Entity, With<PauseOverlay>>,
|
|
||||||
mut commands: Commands,
|
|
||||||
) {
|
|
||||||
if !pause.is_changed() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if pause.paused {
|
|
||||||
if overlay.is_empty() {
|
|
||||||
commands.spawn((
|
|
||||||
PauseOverlay,
|
|
||||||
Node {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
left: px(0),
|
|
||||||
right: px(0),
|
|
||||||
top: px(0),
|
|
||||||
bottom: px(0),
|
|
||||||
align_items: AlignItems::Center,
|
|
||||||
justify_content: JustifyContent::Center,
|
|
||||||
flex_direction: FlexDirection::Column,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.7)),
|
|
||||||
ZIndex(100),
|
|
||||||
children![
|
|
||||||
(
|
|
||||||
Text::new("Paused"),
|
|
||||||
TextFont::from_font_size(crate::menus::style::H1_SIZE as f32),
|
|
||||||
TextColor(Color::WHITE),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
Text::new("Press Esc or Start to resume"),
|
|
||||||
TextFont::from_font_size(crate::menus::style::TEXT_SIZE as f32),
|
|
||||||
TextColor(Color::WHITE),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for entity in &overlay {
|
|
||||||
commands.entity(entity).despawn();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user