Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 committed Jul 16, 2023
1 parent c3d71d3 commit ebac6db
Show file tree
Hide file tree
Showing 9 changed files with 137 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.

27 changes: 26 additions & 1 deletion crates/lobby_client/src/endpoints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use de_lobby_model::{GameListing, GameSetup, Token, UserWithPassword, UsernameAndPassword};
use de_lobby_model::{Game, GameListing, GameSetup, Token, UserWithPassword, UsernameAndPassword};
use reqwest::{header::HeaderValue, Method, Request};
use serde::Serialize;
use url::Url;
Expand Down Expand Up @@ -95,6 +95,28 @@ impl LobbyRequestCreator for ListGamesRequest {
}
}

pub struct GetGameRequest(String);

impl GetGameRequest {
pub fn new(id: impl ToString) -> Self {
Self(id.to_string())
}
}

impl LobbyRequest for GetGameRequest {
type Response = Game;
}

impl LobbyRequestCreator for GetGameRequest {
fn path(&self) -> Cow<str> {
encode(&["a", "games", self.0.as_str()])
}

fn create(&self, url: Url) -> Request {
Request::new(Method::GET, url)
}
}

pub struct JoinGameRequest(String);

impl JoinGameRequest {
Expand Down Expand Up @@ -158,6 +180,8 @@ fn encode(parts: &[&str]) -> Cow<'static, str> {

#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use de_lobby_model::{GameConfig, GameMap, User};

use super::*;
Expand Down Expand Up @@ -214,6 +238,7 @@ mod tests {
);
let request =
CreateGameRequest::new(GameSetup::new("127.0.0.1:8082".parse().unwrap(), config));

assert_eq!(request.path().as_ref(), "/a/games");

let request = request.create(Url::parse("http://example.com/a/games").unwrap());
Expand Down
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 @@ -18,6 +18,7 @@ de_gui.workspace = true
de_lobby_client.workspace = true
de_lobby_model.workspace = true
de_map.workspace = true
de_multiplayer.workspace = true

# Other
async-std.workspace = true
Expand Down
36 changes: 9 additions & 27 deletions crates/menu/src/create.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
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 crate::{
mapselection::{MapSelectedEvent, SelectMapEvent},
menu::Menu,
requests::{Receiver, RequestsPlugin, Sender},
setup::GameConfigRes,
MenuState,
};

pub(crate) struct CreateGamePlugin;

impl Plugin for CreateGamePlugin {
fn build(&self, app: &mut App) {
app.add_plugin(RequestsPlugin::<CreateGameRequest>::new())
.add_event::<CreateGameEvent>()
app.add_event::<CreateGameEvent>()
.add_system(setup.in_schedule(OnEnter(MenuState::GameCreation)))
.add_system(cleanup.in_schedule(OnExit(MenuState::GameCreation)))
.add_system(
Expand All @@ -40,8 +36,7 @@ impl Plugin for CreateGamePlugin {
.run_if(on_event::<CreateGameEvent>())
.after(CreateSet::Buttons)
.after(CreateSet::MapSelected),
)
.add_system(response_system.run_if(in_state(MenuState::GameCreation)));
);
}
}

Expand Down Expand Up @@ -237,11 +232,12 @@ fn map_selected_system(
}

fn create_game_system(
mut commands: Commands,
inputs: Res<Inputs>,
texts: TextBoxQuery,
selected_map: Option<Res<SelectedMap>>,
mut toasts: EventWriter<ToastEvent>,
mut sender: Sender<CreateGameRequest>,
mut next_state: ResMut<NextState<MenuState>>,
) {
let Some(selected_map) = selected_map else {
toasts.send(ToastEvent::new("No map selected."));
Expand All @@ -257,26 +253,12 @@ 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<MenuState>>,
mut receiver: Receiver<CreateGameRequest>,
mut toasts: EventWriter<ToastEvent>,
) {
if let Some(result) = receiver.receive() {
match result {
Ok(_) => next_state.set(MenuState::MultiPlayerGame),
Err(error) => toasts.send(ToastEvent::new(error)),
}
}
commands.insert_resource(GameConfigRes::new(game_config));
next_state.set(MenuState::GameSetup);
}
2 changes: 2 additions & 0 deletions crates/menu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod mainmenu;
mod mapselection;
mod menu;
mod requests;
mod setup;
mod signin;
mod singleplayer;

Expand Down Expand Up @@ -60,6 +61,7 @@ pub(crate) enum MenuState {
SignIn,
GameListing,
GameCreation,
GameSetup,
MultiPlayerGame,
AfterGame,
}
Expand Down
89 changes: 89 additions & 0 deletions crates/menu/src/setup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use bevy::prelude::*;
use de_gui::ToastEvent;
use de_lobby_client::CreateGameRequest;
use de_lobby_model::{GameConfig, GameSetup};
use de_multiplayer::{
GameOpenedEvent, NetGameConf, ServerPort, ShutdownMultiplayerEvent, StartMultiplayerEvent,
};

use crate::{
requests::{Receiver, RequestsPlugin, Sender},
MenuState,
};

pub(crate) struct CreateGamePlugin;

impl Plugin for CreateGamePlugin {
fn build(&self, app: &mut App) {
app.add_plugin(RequestsPlugin::<CreateGameRequest>::new())
.add_system(setup_network.in_schedule(OnEnter(MenuState::GameSetup)))
.add_system(cleanup.in_schedule(OnExit(MenuState::GameSetup)))
.add_system(
create_game_in_lobby
.run_if(in_state(MenuState::GameSetup))
.run_if(on_event::<GameOpenedEvent>()),
)
.add_system(handle_lobby_response.run_if(in_state(MenuState::GameSetup)));
}
}

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

impl GameConfigRes {
pub(crate) fn new(config: GameConfig) -> Self {
Self(config)
}
}

fn setup_network(config: Res<GameConfigRes>, mut multiplayer: EventWriter<StartMultiplayerEvent>) {
multiplayer.send(StartMultiplayerEvent::new(NetGameConf::new(
config.0.max_players().try_into().unwrap(),
// TODO not localhost
IpAddr::V4(Ipv4Addr::LOCALHOST),
// TODO not fixed port
ServerPort::Main(8082),
)));
}

fn cleanup(mut commands: Commands) {
commands.remove_resource::<GameConfigRes>();

// shutdown multiplayer if not entering MenuState::MultiPlayerGame
}

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;
};

// TODO not localhost
let server = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), opened_event.0);
let game_setup = GameSetup::new(server, config.0.clone());
sender.send(CreateGameRequest::new(game_setup));
}

fn handle_lobby_response(
mut next_state: ResMut<NextState<MenuState>>,
mut receiver: Receiver<CreateGameRequest>,
mut multiplayer: EventWriter<ShutdownMultiplayerEvent>,
mut toasts: EventWriter<ToastEvent>,
) {
if let Some(result) = receiver.receive() {
match result {
Ok(_) => next_state.set(MenuState::MultiPlayerGame),
Err(error) => {
multiplayer.send(ShutdownMultiplayerEvent);
toasts.send(ToastEvent::new(error));
}
}
}
}

// TODO handle multiplayer errors
8 changes: 7 additions & 1 deletion crates/multiplayer/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ pub(crate) struct GamePlugin;

impl Plugin for GamePlugin {
fn build(&self, app: &mut App) {
app.add_system(setup.in_schedule(OnEnter(NetState::Connected)))
app.add_event::<GameOpenedEvent>()
.add_system(setup.in_schedule(OnEnter(NetState::Connected)))
.add_system(cleanup.in_schedule(OnEnter(NetState::None)))
.add_system(open_or_join.in_schedule(OnEnter(NetState::Connected)))
.add_system(
Expand All @@ -35,6 +36,9 @@ impl Plugin for GamePlugin {
}
}

/// A new game on the given port was just opened.
pub struct GameOpenedEvent(pub u16);

#[derive(Resource)]
pub(crate) struct Players {
local: Option<Player>,
Expand Down Expand Up @@ -74,6 +78,7 @@ fn process_from_server(
mut ports: ResMut<Ports>,
mut events: EventReader<FromMainServerEvent>,
mut outputs: EventWriter<ToGameServerEvent<true>>,
mut opened: EventWriter<GameOpenedEvent>,
mut fatals: EventWriter<FatalErrorEvent>,
) {
for event in events.iter() {
Expand All @@ -86,6 +91,7 @@ fn process_from_server(
info!("Game on port {} opened.", *port);
// Send something to open NAT.
outputs.send(ToGame::Ping(u32::MAX).into());
opened.send(GameOpenedEvent(*port));
}
Err(err) => {
fatals.send(FatalErrorEvent::new(format!("Invalid GameOpened: {err:?}")));
Expand Down
1 change: 1 addition & 0 deletions crates/multiplayer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use stats::StatsPlugin;

pub use crate::{
config::{NetGameConf, ServerPort},
game::GameOpenedEvent,
lifecycle::{ShutdownMultiplayerEvent, StartMultiplayerEvent},
netstate::NetState,
};
Expand Down

0 comments on commit ebac6db

Please sign in to comment.