Skip to content

Commit

Permalink
Game setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 committed Aug 2, 2023
1 parent e33d82c commit 79deb7d
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/lobby_model/src/games.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl validation::Validatable for GameSetup {
}
}

#[derive(Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameConfig {
name: String,
Expand Down
1 change: 1 addition & 0 deletions crates/menu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories.workspace = true

[dependencies]
# DE
de_conf.workspace = true
de_core.workspace = true
de_gui.workspace = true
de_lobby_client.workspace = true
Expand Down
34 changes: 6 additions & 28 deletions crates/menu/src/multiplayer/create.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
use std::net::SocketAddr;

use bevy::prelude::*;
use de_gui::{
ButtonCommands, ButtonOps, GuiCommands, LabelCommands, OuterStyle, TextBoxCommands,
TextBoxQuery, ToastEvent,
};
use de_lobby_client::CreateGameRequest;
use de_lobby_model::{GameConfig, GameMap, GameSetup, Validatable};
use de_lobby_model::{GameConfig, GameMap, Validatable};
use de_map::hash::MapHash;

use super::MultiplayerState;
use super::{setup::SetupGameEvent, MultiplayerState};
use crate::{
mapselection::{MapSelectedEvent, SelectMapEvent},
menu::Menu,
multiplayer::requests::{Receiver, RequestsPlugin, Sender},
};

pub(super) struct CreateGamePlugin;

impl Plugin for CreateGamePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(RequestsPlugin::<CreateGameRequest>::new())
.add_event::<CreateGameEvent>()
app.add_event::<CreateGameEvent>()
.add_systems(OnEnter(MultiplayerState::GameCreation), setup)
.add_systems(OnExit(MultiplayerState::GameCreation), cleanup)
.add_systems(
Expand All @@ -33,7 +28,6 @@ impl Plugin for CreateGamePlugin {
.run_if(on_event::<CreateGameEvent>())
.after(CreateSet::Buttons)
.after(CreateSet::MapSelected),
response_system,
)
.run_if(in_state(MultiplayerState::GameCreation)),
);
Expand Down Expand Up @@ -243,7 +237,7 @@ fn create_game_system(
texts: TextBoxQuery,
selected_map: Option<Res<SelectedMap>>,
mut toasts: EventWriter<ToastEvent>,
mut sender: Sender<CreateGameRequest>,
mut setup_events: EventWriter<SetupGameEvent>,
) {
let Some(selected_map) = selected_map else {
toasts.send(ToastEvent::new("No map selected."));
Expand All @@ -259,26 +253,10 @@ fn create_game_system(
}
};

let game_server: SocketAddr = "127.0.0.1:8082".parse().unwrap();
let game_config = GameConfig::new(name, max_players, selected_map.0.clone());
let game_setup = GameSetup::new(game_server, game_config);
if let Err(error) = game_setup.validate() {
if let Err(error) = game_config.validate() {
toasts.send(ToastEvent::new(format!("{error}")));
return;
}

sender.send(CreateGameRequest::new(game_setup));
}

fn response_system(
mut next_state: ResMut<NextState<MultiplayerState>>,
mut receiver: Receiver<CreateGameRequest>,
mut toasts: EventWriter<ToastEvent>,
) {
if let Some(result) = receiver.receive() {
match result {
Ok(_) => next_state.set(MultiplayerState::GameJoined),
Err(error) => toasts.send(ToastEvent::new(error)),
}
}
setup_events.send(SetupGameEvent::new(game_config));
}
8 changes: 7 additions & 1 deletion crates/menu/src/multiplayer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ use bevy::prelude::*;
use de_core::nested_state;
use de_multiplayer::MultiplayerShuttingDownEvent;

use self::{create::CreateGamePlugin, gamelisting::GameListingPlugin, signin::SignInPlugin};
use self::{
create::CreateGamePlugin, gamelisting::GameListingPlugin, setup::SetupGamePlugin,
signin::SignInPlugin,
};
use crate::{menu::ScreenStatePlugin, MenuState};

mod create;
mod gamelisting;
mod requests;
mod setup;
mod signin;

pub(super) struct MultiplayerPlugin;
Expand All @@ -20,6 +24,7 @@ impl Plugin for MultiplayerPlugin {
SignInPlugin,
GameListingPlugin,
CreateGamePlugin,
SetupGamePlugin,
))
.add_systems(
PostUpdate,
Expand All @@ -38,6 +43,7 @@ nested_state!(
SignIn,
GameListing,
GameCreation,
GameSetup,
GameJoined,
}
);
Expand Down
123 changes: 123 additions & 0 deletions crates/menu/src/multiplayer/setup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use bevy::prelude::*;
use de_conf::Configuration;
use de_gui::ToastEvent;
use de_lobby_client::CreateGameRequest;
use de_lobby_model::{GameConfig, GameSetup};
use de_multiplayer::{
GameOpenedEvent, NetGameConf, ServerPort, ShutdownMultiplayerEvent, StartMultiplayerEvent,
};

use super::{
requests::{Receiver, Sender},
MultiplayerState,
};
use crate::MenuState;

pub(crate) struct SetupGamePlugin;

impl Plugin for SetupGamePlugin {
fn build(&self, app: &mut App) {
app.add_event::<SetupGameEvent>()
.add_systems(OnEnter(MultiplayerState::GameSetup), setup_network)
.add_systems(OnExit(MultiplayerState::GameSetup), cleanup)
.add_systems(
PreUpdate,
handle_setup_event.run_if(in_state(MenuState::Multiplayer)),
)
.add_systems(
Update,
(create_game_in_lobby, handle_lobby_response)
.run_if(in_state(MultiplayerState::GameSetup)),
);
}
}

/// Send this event to initiate new multiplayer setup.
///
/// The game will be opened at a DE Connector and registered at a DE Lobby.
/// Once this is done, the menu transitions to
/// [`MultiplayerState::GameJoined`].
#[derive(Event)]
pub(super) struct SetupGameEvent {
config: GameConfig,
}

impl SetupGameEvent {
pub(super) fn new(config: GameConfig) -> Self {
Self { config }
}
}

#[derive(Resource)]
pub(crate) struct GameConfigRes(GameConfig);

fn handle_setup_event(
mut commands: Commands,
mut next_state: ResMut<NextState<MultiplayerState>>,
mut events: EventReader<SetupGameEvent>,
) {
let Some(event) = events.iter().last() else {
return;
};

commands.insert_resource(GameConfigRes(event.config.clone()));
next_state.set(MultiplayerState::GameSetup);
}

fn cleanup(
mut commands: Commands,
state: Res<State<MultiplayerState>>,
mut shutdown: EventWriter<ShutdownMultiplayerEvent>,
) {
commands.remove_resource::<GameConfigRes>();

if state.as_ref() != &MultiplayerState::GameJoined {
shutdown.send(ShutdownMultiplayerEvent);
}
}

fn setup_network(
config: Res<Configuration>,
game_config: Res<GameConfigRes>,
mut multiplayer: EventWriter<StartMultiplayerEvent>,
) {
let connector_conf = config.multiplayer().connector();
let net_game_conf = NetGameConf::new(
game_config.0.max_players().try_into().unwrap(),
connector_conf.ip(),
ServerPort::Main(connector_conf.port()),
);
multiplayer.send(StartMultiplayerEvent::new(net_game_conf));
}

fn create_game_in_lobby(
config: Res<GameConfigRes>,
mut opened_events: EventReader<GameOpenedEvent>,
mut sender: Sender<CreateGameRequest>,
) {
let Some(opened_event) = opened_events.iter().last() else {
return;
};

let game_setup = GameSetup::new(opened_event.0, config.0.clone());
sender.send(CreateGameRequest::new(game_setup));
}

fn handle_lobby_response(
mut next_state: ResMut<NextState<MultiplayerState>>,
mut receiver: Receiver<CreateGameRequest>,
mut toasts: EventWriter<ToastEvent>,
) {
while let Some(result) = receiver.receive() {
match result {
Ok(_) => {
info!("Game successfully created.");
next_state.set(MultiplayerState::GameJoined);
}
Err(error) => {
toasts.send(ToastEvent::new(error));
next_state.set(MultiplayerState::SignIn);
}
}
}
}

0 comments on commit 79deb7d

Please sign in to comment.