feat: add connecting to the server

This commit is contained in:
2026-08-21 14:16:34 +02:00
parent c0cfb67eec
commit 20d922c56e
9 changed files with 99 additions and 22 deletions

View File

@@ -9,9 +9,10 @@ use macroquad::{
color::{BLACK, WHITE}, color::{BLACK, WHITE},
math::vec2, math::vec2,
miniquad::{self, conf::LinuxBackend::WaylandWithX11Fallback}, miniquad::{self, conf::LinuxBackend::WaylandWithX11Fallback},
text::draw_text,
texture::{DrawTextureParams, draw_texture_ex, load_texture}, texture::{DrawTextureParams, draw_texture_ex, load_texture},
ui::{Skin, root_ui}, ui::{Skin, root_ui},
window::{Conf, screen_height, screen_width}, window::{Conf, next_frame, screen_height, screen_width},
}; };
fn window_conf() -> Conf { fn window_conf() -> Conf {
@@ -70,7 +71,7 @@ pub async fn main() {
}, },
); );
match state { match &state {
GuiState::MainMenu => { GuiState::MainMenu => {
draw_main_menu(&mut state).await; draw_main_menu(&mut state).await;
} }
@@ -87,16 +88,36 @@ pub async fn main() {
draw_server_selection(&mut state, &mut context).await; draw_server_selection(&mut state, &mut context).await;
} }
GuiState::Connecting(receiver) => {
draw_text("Connecting...", 0.0, 0.0, 64.0, BLACK);
match receiver.try_recv() {
Ok(client) => {
if let Some(client) = client {
draw_text("Connected!", 0.0, 0.0, 64.0, BLACK);
state = GuiState::Game(client);
} else {
draw_text("Could not connect!", 0.0, 0.0, 64.0, BLACK);
}
}
Err(_) => {
draw_text("Error", 0.0, 0.0, 64.0, BLACK);
}
}
}
GuiState::Settings => { GuiState::Settings => {
todo!(); todo!();
} }
GuiState::Game => {
todo!(); GuiState::Game(client) => {
draw_text("Gamer time", 100.0, 100.0, 64.0, BLACK);
} }
GuiState::Exit => { GuiState::Exit => {
break; break;
} }
} }
next_frame().await;
} }
} }

View File

@@ -6,7 +6,7 @@ use uuid::Uuid;
use crate::logic::board::{board::Board, field::Field}; use crate::logic::board::{board::Board, field::Field};
/// View of the board, without any methods. Meant for sending over network /// View of the board, without any methods. Meant for sending over network
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
pub struct BoardView { pub struct BoardView {
pub board: Vec<Field>, pub board: Vec<Field>,
pub size: usize, pub size: usize,

View File

@@ -11,6 +11,7 @@ use crate::ui::{
state::{ state::{
GameContext, GameContext,
GuiState::{self}, GuiState::{self},
connect_to_server,
}, },
}; };
@@ -30,25 +31,25 @@ pub async fn draw_dificulty_selection(state: &mut GuiState, context: &mut GameCo
.ui(&mut root_ui(), |ui| { .ui(&mut root_ui(), |ui| {
menu_builder.label(ui, "Difficulty Selection"); menu_builder.label(ui, "Difficulty Selection");
// TODO! refactor this ugly ass code
if menu_builder.button(ui, "Easy") { if menu_builder.button(ui, "Easy") {
context.difficulty = crate::super_advanced_ai::BotDificulty::Easy; context.difficulty = crate::super_advanced_ai::BotDificulty::Easy;
*state = GuiState::Game; *state = GuiState::Connecting(connect_to_server(context.clone()));
} }
if menu_builder.button(ui, "Medium") { if menu_builder.button(ui, "Medium") {
context.difficulty = crate::super_advanced_ai::BotDificulty::Normal; context.difficulty = crate::super_advanced_ai::BotDificulty::Normal;
*state = GuiState::Game; *state = GuiState::Connecting(connect_to_server(context.clone()));
} }
if menu_builder.button(ui, "Hard") { if menu_builder.button(ui, "Hard") {
context.difficulty = crate::super_advanced_ai::BotDificulty::Hard; context.difficulty = crate::super_advanced_ai::BotDificulty::Hard;
*state = GuiState::Game; *state = GuiState::Connecting(connect_to_server(context.clone()));
} }
if menu_builder.button(ui, "Go back") { if menu_builder.button(ui, "Go back") {
*state = GuiState::ModeSelection; *state = GuiState::ModeSelection;
} }
}); });
next_frame().await;
} }

38
src/ui/macroquad/game.rs Normal file
View File

@@ -0,0 +1,38 @@
use tokio::sync::mpsc::Receiver;
use crate::{
logic::board::board_view::BoardView,
network::{client::Client, message::ServerMessage},
ui::state::GameContext,
};
pub struct GameClient {
client: Client,
update_receiver: Receiver<ServerMessage>,
board: BoardView,
player_name: String,
enemy_name: String, // TODO! Server should give this info to us (it doesn't rn)
}
impl GameClient {
pub async fn new(context: &GameContext) -> Option<Self> {
let Some(mut client) = Client::new(None).await else {
return None;
};
let Some(update_receiver) = client.get_update_receiver() else {
return None;
};
let board = BoardView::default();
Some(Self {
client,
update_receiver,
board,
player_name: "Morbius".to_string(),
enemy_name: "Milo".to_string(),
})
}
}

View File

@@ -8,7 +8,6 @@ use macroquad::{
use crate::ui::{macroquad::menu_builder::MenuBuilder, state::GuiState}; use crate::ui::{macroquad::menu_builder::MenuBuilder, state::GuiState};
pub async fn draw_main_menu(state: &mut GuiState) { pub async fn draw_main_menu(state: &mut GuiState) {
let menu_size = vec2(screen_width() * 0.5, screen_height() * 0.5); let menu_size = vec2(screen_width() * 0.5, screen_height() * 0.5);
let menu_pos = vec2( let menu_pos = vec2(
@@ -37,6 +36,4 @@ pub async fn draw_main_menu(state: &mut GuiState) {
*state = GuiState::Exit; *state = GuiState::Exit;
} }
}); });
next_frame().await;
} }

View File

@@ -1,4 +1,5 @@
pub mod difficulty_selection; pub mod difficulty_selection;
pub mod game;
pub mod main_menu; pub mod main_menu;
mod menu_builder; mod menu_builder;
pub mod mode_selection; pub mod mode_selection;

View File

@@ -43,6 +43,4 @@ pub async fn draw_mode_selection(state: &mut GuiState, context: &mut GameContext
*state = GuiState::MainMenu; *state = GuiState::MainMenu;
} }
}); });
next_frame().await;
} }

View File

@@ -11,6 +11,7 @@ use crate::ui::{
state::{ state::{
GameContext, GameContext,
GuiState::{self}, GuiState::{self},
connect_to_server,
}, },
}; };
@@ -40,7 +41,7 @@ pub async fn draw_server_selection(state: &mut GuiState, context: &mut GameConte
if menu_builder.button(ui, "Connect") { if menu_builder.button(ui, "Connect") {
context.gamemode = crate::ui::state::GameMode::Multiplayer { is_hosting: false }; context.gamemode = crate::ui::state::GameMode::Multiplayer { is_hosting: false };
*state = GuiState::Game; *state = GuiState::Connecting(connect_to_server(context.clone()));
// TODO Validate url before connecting or something like that // TODO Validate url before connecting or something like that
} }
@@ -48,6 +49,4 @@ pub async fn draw_server_selection(state: &mut GuiState, context: &mut GameConte
*state = GuiState::ModeSelection; *state = GuiState::ModeSelection;
} }
}); });
next_frame().await;
} }

View File

@@ -1,4 +1,6 @@
use crate::super_advanced_ai::BotDificulty; use std::sync::mpsc::{self, Receiver};
use crate::{super_advanced_ai::BotDificulty, ui::macroquad::game::GameClient};
#[derive(Default)] #[derive(Default)]
pub enum GuiState { pub enum GuiState {
@@ -9,12 +11,14 @@ pub enum GuiState {
DificultySelection, DificultySelection,
ServerSelection, ServerSelection,
Connecting(Receiver<Option<GameClient>>),
Settings, Settings,
Game, Game(GameClient),
Exit, Exit,
} }
#[derive(Default)] #[derive(Default, Clone, Copy)]
pub enum GameMode { pub enum GameMode {
#[default] #[default]
Singleplayer, Singleplayer,
@@ -23,9 +27,27 @@ pub enum GameMode {
}, },
} }
#[derive(Default)] #[derive(Default, Clone)]
pub struct GameContext { pub struct GameContext {
pub difficulty: BotDificulty, pub difficulty: BotDificulty,
pub gamemode: GameMode, pub gamemode: GameMode,
pub server_url_buffer: String, pub server_url_buffer: String,
} }
// TODO! Move this
pub fn connect_to_server(context: GameContext) -> Receiver<Option<GameClient>> {
let (tx, rc) = mpsc::channel::<Option<GameClient>>();
let context_clone = context.clone();
let _ = std::thread::spawn(move || {
let rt = tokio::runtime::Runtime::new().unwrap();
let client_option = rt.block_on(async { GameClient::new(&context_clone).await });
let _ = tx.send(client_option);
std::thread::park();
});
rc
}