diff --git a/werewolves-proto/src/message/host.rs b/werewolves-proto/src/message/host.rs index 8f3f800..0c00be8 100644 --- a/werewolves-proto/src/message/host.rs +++ b/werewolves-proto/src/message/host.rs @@ -60,8 +60,7 @@ pub enum HostLobbyMessage { Start, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[cfg_attr(test, derive(werewolves_macros::Titles))] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, werewolves_macros::Titles)] pub enum ServerToHostMessage { Disconnect, Daytime { diff --git a/werewolves/src/pages/client.rs b/werewolves/src/clients/client/client.rs similarity index 95% rename from werewolves/src/pages/client.rs rename to werewolves/src/clients/client/client.rs index 6a715ce..7095742 100644 --- a/werewolves/src/pages/client.rs +++ b/werewolves/src/clients/client/client.rs @@ -9,6 +9,7 @@ use gloo::{ net::websocket::{self, futures::WebSocket}, storage::{LocalStorage, Storage, errors::StorageError}, }; +use instant::Instant; use serde::Serialize; use werewolves_proto::{ error::GameError, @@ -28,10 +29,7 @@ use crate::{ storage::StorageKey, }; -use super::WerewolfError; - -const DEBUG_URL: &str = "ws://192.168.1.162:8080/connect/client"; -const LIVE_URL: &str = "wss://wolf.emilis.dev/connect/client"; +use crate::WerewolfError; #[derive(Debug)] pub enum Message { @@ -48,11 +46,20 @@ pub struct Connection { recv: Receiver, } +fn url() -> String { + format!( + "{}client", + option_env!("LOCAL") + .map(|_| super::DEBUG_URL) + .unwrap_or(super::LIVE_URL) + ) +} + impl Connection { async fn connect_ws() -> WebSocket { - let url = option_env!("LOCAL").map(|_| DEBUG_URL).unwrap_or(LIVE_URL); + let url = url(); loop { - match WebSocket::open(url) { + match WebSocket::open(&url) { Ok(ws) => break ws, Err(err) => { log::error!("connect: {err}"); @@ -78,8 +85,18 @@ impl Connection { } async fn run(mut self) { - let url = option_env!("LOCAL").map(|_| DEBUG_URL).unwrap_or(LIVE_URL); + const CONNECT_WAIT: Duration = Duration::from_secs(3); + let url = url(); + let mut last_connect: Option = None; 'outer: loop { + if let Some(last_connect) = last_connect.as_ref() { + let time_since_last = Instant::now() - *last_connect; + if time_since_last <= CONNECT_WAIT { + yew::platform::time::sleep(CONNECT_WAIT.saturating_sub(time_since_last)).await; + continue; + } + } + last_connect = Some(Instant::now()); log::info!("connecting to {url}"); let mut ws = Self::connect_ws().await.fuse(); log::info!("connected to {url}"); diff --git a/werewolves/src/pages/host.rs b/werewolves/src/clients/host/host.rs similarity index 92% rename from werewolves/src/pages/host.rs rename to werewolves/src/clients/host/host.rs index e8ed05e..62a15e4 100644 --- a/werewolves/src/pages/host.rs +++ b/werewolves/src/clients/host/host.rs @@ -5,12 +5,13 @@ use futures::{ channel::mpsc::{Receiver, Sender}, }; use gloo::net::websocket::{self, futures::WebSocket}; +use instant::Instant; use serde::Serialize; use werewolves_proto::{ error::GameError, game::{GameOver, GameSettings}, message::{ - CharacterState, Identification, PlayerState, PublicIdentity, Target, + CharacterState, PlayerState, PublicIdentity, Target, host::{ HostDayMessage, HostGameMessage, HostLobbyMessage, HostMessage, HostNightMessage, ServerToHostMessage, @@ -30,15 +31,21 @@ use crate::{ }, }; -use super::WerewolfError; +use crate::WerewolfError; -const DEBUG_URL: &str = "ws://192.168.1.162:8080/connect/host"; -const LIVE_URL: &str = "wss://wolf.emilis.dev/connect/host"; +fn url() -> String { + format!( + "{}host", + option_env!("LOCAL") + .map(|_| super::DEBUG_URL) + .unwrap_or(super::LIVE_URL) + ) +} async fn connect_ws() -> WebSocket { - let url = option_env!("LOCAL").map(|_| DEBUG_URL).unwrap_or(LIVE_URL); + let url = url(); loop { - match WebSocket::open(url) { + match WebSocket::open(&url) { Ok(ws) => break ws, Err(err) => { log::error!("connect: {err}"); @@ -64,16 +71,31 @@ fn encode_message(msg: &impl Serialize) -> websocket::Message { } async fn worker(mut recv: Receiver, scope: Scope) { - let url = option_env!("LOCAL").map(|_| DEBUG_URL).unwrap_or(LIVE_URL); + const CONNECT_WAIT: Duration = Duration::from_secs(3); + let url = url(); + let mut last_connect: Option = None; 'outer: loop { - log::info!("connecting to {url}"); + if let Some(last_connect) = last_connect.as_ref() { + let time_since_last = Instant::now() - *last_connect; + if time_since_last <= CONNECT_WAIT { + log::debug!("waiting to reconnect"); + yew::platform::time::sleep(CONNECT_WAIT.saturating_sub(time_since_last)).await; + log::debug!("wait over"); + continue; + } + log::debug!("reconnecting"); + } + last_connect = Some(Instant::now()); + log::debug!("connecting to {url}"); let mut ws = connect_ws().await.fuse(); - log::info!("connected to {url}"); + log::debug!("connected to {url}"); + log::debug!("sending GetState message"); if let Err(err) = ws.send(encode_message(&HostMessage::GetState)).await { log::error!("sending request for state: {err}"); continue 'outer; } + log::debug!("initial GetState message sent"); loop { let msg = futures::select! { @@ -137,7 +159,8 @@ async fn worker(mut recv: Receiver, scope: Scope) { }; match parse { Ok(msg) => { - log::debug!("got message: {msg:?}"); + log::debug!("got message: {:?}", msg.title()); + log::trace!("message content: {msg:?}"); scope.send_message::(msg.into()) } Err(err) => { @@ -553,7 +576,11 @@ impl Component for Host { } if state { - self.send.close_channel(); + let (discard_send, mut discard_recv) = futures::channel::mpsc::channel(10); + self.send = discard_send; + yew::platform::spawn_local(async move { + while discard_recv.next().await.is_some() {} + }); } self.debug = false; self.error_callback = Callback::noop(); diff --git a/werewolves/src/clients/mod.rs b/werewolves/src/clients/mod.rs new file mode 100644 index 0000000..2005c31 --- /dev/null +++ b/werewolves/src/clients/mod.rs @@ -0,0 +1,10 @@ +pub mod client { + include!("client/client.rs"); +} +pub mod host { + include!("host/host.rs"); +} +// mod socket; + +const DEBUG_URL: &str = "ws://192.168.1.162:8080/connect/"; +const LIVE_URL: &str = "wss://wolf.emilis.dev/connect/"; diff --git a/werewolves/src/main.rs b/werewolves/src/main.rs index c94585c..ce39786 100644 --- a/werewolves/src/main.rs +++ b/werewolves/src/main.rs @@ -1,4 +1,5 @@ mod assets; +mod clients; mod storage; mod components { werewolves_macros::include_path!("werewolves/src/components"); @@ -13,7 +14,7 @@ mod pages { mod callback; use core::num::NonZeroU8; -use pages::{Client, ErrorComponent, Host, WerewolfError}; +use pages::{ErrorComponent, WerewolfError}; use web_sys::Url; use werewolves_proto::{ message::{Identification, PublicIdentity}, @@ -21,7 +22,10 @@ use werewolves_proto::{ }; use yew::prelude::*; -use crate::pages::ClientProps; +use crate::clients::{ + client::{Client, ClientProps, Message}, + host::{Host, HostEvent}, +}; fn main() { wasm_logger::init(wasm_logger::Config::new(log::Level::Trace)); @@ -39,9 +43,9 @@ fn main() { if path.starts_with("/host") { let host = yew::Renderer::::with_root(app_element).render(); - host.send_message(pages::HostEvent::SetErrorCallback(error_callback)); + host.send_message(HostEvent::SetErrorCallback(error_callback)); if path.starts_with("/host/big") { - host.send_message(pages::HostEvent::SetBigScreenState(true)); + host.send_message(HostEvent::SetBigScreenState(true)); } } else if path.starts_with("/many-client") { let mut number = 1..=0xFFu8; @@ -85,7 +89,7 @@ fn main() { let client = yew::Renderer::::with_root_and_props(dupe, ClientProps { auto_join: true }) .render(); - client.send_message(pages::Message::ForceIdentity(Identification { + client.send_message(Message::ForceIdentity(Identification { player_id, public: PublicIdentity { name: name.to_string(), @@ -93,7 +97,7 @@ fn main() { number: NonZeroU8::new(number.next().unwrap()).unwrap(), }, })); - client.send_message(pages::Message::SetErrorCallback(error_callback.clone())); + client.send_message(Message::SetErrorCallback(error_callback.clone())); } } else { let client = yew::Renderer::::with_root_and_props( @@ -101,6 +105,6 @@ fn main() { ClientProps { auto_join: false }, ) .render(); - client.send_message(pages::Message::SetErrorCallback(error_callback)); + client.send_message(Message::SetErrorCallback(error_callback)); } } diff --git a/werewolves/src/pages/error.rs b/werewolves/src/pages/error.rs index e376862..16291d2 100644 --- a/werewolves/src/pages/error.rs +++ b/werewolves/src/pages/error.rs @@ -13,8 +13,6 @@ pub enum WerewolfError { InvalidTarget, #[error("send error: {0}")] SendError(#[from] futures::channel::mpsc::SendError), - #[error("[{0}] {1}")] - NamedGameError(&'static str, GameError), } impl From for WerewolfError {