diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index fd0a427..44dfae3 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -77,7 +77,7 @@ jobs: release: - needs: test-data-upload + needs: [engine, server, ui] if: github.ref == 'refs/heads/master' uses: ./.github/workflows/release.yml secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 76e25a0..e6edde8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,9 +12,6 @@ jobs: name: Build and release (master only) runs-on: self-hosted steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Build Engine for Linux run: | cd $(git rev-parse --show-toplevel) diff --git a/ui/src/connection.rs b/ui/src/connection.rs new file mode 100644 index 0000000..006c88c --- /dev/null +++ b/ui/src/connection.rs @@ -0,0 +1,117 @@ +use engine::{chessmove::ChessMove, gameend::GameEnd}; +use futures_util::{SinkExt, StreamExt}; +use local_ip_address::local_ip; +use log::{error, info, warn}; +use serde::{Deserialize, Serialize}; +use std::{ + net::{IpAddr, Ipv4Addr}, + sync::{Arc, Mutex}, +}; +use tokio_tungstenite::connect_async; +use tungstenite::Message; +use url::Url; +use uuid::Uuid; + +use crate::{ChessApp, ClientEvent, SharedGameState}; + +#[derive(Serialize, Deserialize)] +pub enum ServerMessage2 { + GameEnd { + winner: GameEnd, + }, + UIUpdate { + fen: String, + }, + MatchFound { + match_id: Uuid, + color: String, + opponent_name: String, + }, + Ok { + response: Result<(), String>, + }, +} + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +enum ClientMessage { + Join { username: String }, + FindMatch, + Move { step: ChessMove, fen: String }, + Resign, + Chat { text: String }, + RequestLegalMoves { fen: String }, +} + +fn get_ip_address() -> IpAddr { + let ip = local_ip().unwrap_or(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))); + + ip +} + +pub async fn handle_connection( + server_port: &str, + shared_state: SharedGameState, + ui_events: Arc>>, +) -> anyhow::Result<()> { + let address = get_ip_address(); + + //start main loop + let server_address = String::from("ws://") + &address.to_string() + ":" + server_port; + warn!( + "Machine IpAddress is bound for listener. Ip: {}", + server_address + ); + + let url = Url::parse(&server_address)?; + + let (ws_stream, _) = connect_async(url).await?; + let (mut write, mut read) = ws_stream.split(); + + while let Some(message) = read.next().await { + info!("connection"); + match message { + Ok(msg) => { + if msg.is_text() { + let text = msg.to_text().unwrap(); + info!("text: {}", text); + + /*if let Ok(parsed) = serde_json::from_str::(text) { + match parsed { + ServerMessage2::GameEnd { winner } => {} + ServerMessage2::UIUpdate { fen } => {} + ServerMessage2::MatchFound { + match_id, + color, + opponent_name, + } => { + //chess_app.player_color = Some(color); + } + ServerMessage2::Ok { response } => {} + _ => { + error!("Received unkown servermessage2"); + } + } + }*/ + + if let Ok(parsed) = serde_json::from_str::(text) { + // Update shared state with server message + shared_state.update_from_server_message(parsed); + } + + // Send UI events to server + let events = ui_events.lock().unwrap().drain(..).collect::>(); + for event in events { + let message = serde_json::to_string(&event)?; + write.send(Message::Text(message)).await?; + } + } + } + Err(e) => { + error!("Error receiving message: {}", e); + } + } + } + + Ok(()) +} diff --git a/ui/src/main.rs b/ui/src/main.rs index 18a4e92..6258148 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -228,8 +228,6 @@ impl ChessApp { egui::Vec2::new(resolution.0 as f32, resolution.1 as f32) )); } - - ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(self.fullscreen)); } async fn network_handler( server_port: String, @@ -1130,7 +1128,6 @@ impl eframe::App for ChessApp { ctx.request_repaint(); } } - #[cfg(test)] mod tests { use super::*;