moved client/host into separate modules

This commit is contained in:
emilis 2025-10-01 12:35:54 +01:00
parent a11927fb68
commit 862c5004fd
No known key found for this signature in database
6 changed files with 84 additions and 29 deletions

View File

@ -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 {

View File

@ -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<ClientMessage>,
}
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<Instant> = 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}");

View File

@ -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<HostMessage>, scope: Scope<Host>) {
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<Instant> = 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<HostMessage>, scope: Scope<Host>) {
};
match parse {
Ok(msg) => {
log::debug!("got message: {msg:?}");
log::debug!("got message: {:?}", msg.title());
log::trace!("message content: {msg:?}");
scope.send_message::<HostEvent>(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();

View File

@ -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/";

View File

@ -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::<Host>::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::<Client>::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::<Client>::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));
}
}

View File

@ -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<StorageError> for WerewolfError {