Integrate a remote playtesting front-end
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
parent
3accb03ae5
commit
095bc8509c
@ -0,0 +1,149 @@
|
||||
use crate::app::BoardView;
|
||||
use crate::types::SelectedTile;
|
||||
use board_network::protocol::{ClientMessage, ServerMessage};
|
||||
use board_shared::game::Game;
|
||||
use futures::stream::{SplitSink, SplitStream};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use gloo_dialogs::alert;
|
||||
use gloo_net::websocket::futures::WebSocket;
|
||||
use gloo_net::websocket::Message;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use yew::platform::spawn_local;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[derive(Properties)]
|
||||
pub struct RemoteGameViewProps {
|
||||
pub write: Rc<RefCell<SplitSink<WebSocket, Message>>>,
|
||||
pub read: Rc<RefCell<SplitStream<WebSocket>>>,
|
||||
pub player_name: String,
|
||||
pub room_name: Option<String>,
|
||||
}
|
||||
|
||||
impl PartialEq for RemoteGameViewProps {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Rc::ptr_eq(&self.write, &other.write)
|
||||
&& Rc::ptr_eq(&self.read, &other.read)
|
||||
&& self.player_name == other.player_name
|
||||
&& self.room_name == other.room_name
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component(RemoteGameView)]
|
||||
pub fn remote_game_view(
|
||||
RemoteGameViewProps {
|
||||
write,
|
||||
read,
|
||||
player_name,
|
||||
room_name,
|
||||
}: &RemoteGameViewProps,
|
||||
) -> Html {
|
||||
macro_rules! send_client_message {
|
||||
($write:expr, $message:expr) => {{
|
||||
let write = $write.clone();
|
||||
spawn_local(async move {
|
||||
write
|
||||
.borrow_mut()
|
||||
.send(Message::Text(
|
||||
serde_json::to_string(&$message).expect("Cannot serialize"),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
let selected_tile = use_state(|| SelectedTile::None);
|
||||
let is_started = use_state(|| false);
|
||||
let current_player_turn = use_state(|| 0);
|
||||
let game = use_state(Game::default);
|
||||
{
|
||||
let player_name = player_name.clone();
|
||||
let room_name = room_name.clone();
|
||||
let write = write.clone();
|
||||
use_effect_with_deps(
|
||||
move |_| {
|
||||
send_client_message!(
|
||||
write,
|
||||
if let Some(room_name) = room_name {
|
||||
ClientMessage::JoinRoom(room_name, player_name)
|
||||
} else {
|
||||
ClientMessage::CreateRoom(player_name)
|
||||
}
|
||||
);
|
||||
},
|
||||
(),
|
||||
);
|
||||
|
||||
let is_started = is_started.clone();
|
||||
let current_player_turn = current_player_turn.clone();
|
||||
let read = read.clone();
|
||||
use_effect_with_deps(
|
||||
move |_| {
|
||||
spawn_local(async move {
|
||||
while let Some(event) = read.borrow_mut().next().await {
|
||||
if let Message::Text(msg) = event.unwrap() {
|
||||
match serde_json::from_str::<ServerMessage>(&msg) {
|
||||
Ok(ServerMessage::JoinedRoom {
|
||||
room_name,
|
||||
has_started,
|
||||
..
|
||||
}) => {
|
||||
alert(&format!("Joined room {}", room_name));
|
||||
is_started.set(has_started);
|
||||
}
|
||||
Ok(ServerMessage::PlayerTurn(player_id)) => {
|
||||
current_player_turn.set(player_id);
|
||||
is_started.set(true);
|
||||
}
|
||||
r => {
|
||||
alert(&format!("{:?}", r));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|| {}
|
||||
},
|
||||
(),
|
||||
);
|
||||
}
|
||||
|
||||
let on_validate_click = {
|
||||
let write = write.clone();
|
||||
Callback::from(move |_| {
|
||||
send_client_message!(write, ClientMessage::Validate);
|
||||
})
|
||||
};
|
||||
let on_start_game_click = {
|
||||
let write = write.clone();
|
||||
Callback::from(move |_| {
|
||||
send_client_message!(write, ClientMessage::StartGame);
|
||||
})
|
||||
};
|
||||
let on_equals_select = {
|
||||
Callback::from(move |_| {
|
||||
selected_tile.set(SelectedTile::Equals);
|
||||
})
|
||||
};
|
||||
|
||||
html! {
|
||||
<main>
|
||||
<h1>{"Remote Game"}</h1>
|
||||
<BoardView board={game.board.clone()} on_click={Callback::from(|_| {})} />
|
||||
<div class="row">
|
||||
<button onclick={on_equals_select} class="button">{"="}</button>
|
||||
if *is_started {
|
||||
<button onclick={on_validate_click} class="button">{"Validate"}</button>
|
||||
} else {
|
||||
<button onclick={on_start_game_click} class="button">{"Start"}</button>
|
||||
}
|
||||
</div>
|
||||
if *is_started {
|
||||
<div class="row">
|
||||
<p>{format!("Player {}'s turn", *current_player_turn)}</p>
|
||||
</div>
|
||||
}
|
||||
</main>
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
pub enum SelectedTile {
|
||||
InHand(usize),
|
||||
Equals,
|
||||
None,
|
||||
}
|
Loading…
Reference in new issue