use std::future::Future;
use crate::{proto::InitialMessageBatchProto, Action, BitBrokerMessage, Connection, Result};
pub trait BaseGame {
type State: Into<Vec<u8>>;
type Response<'a>: From<&'a [u8]>;
fn initialise(
&mut self,
initial_info: InitialMessageBatchProto,
) -> impl Future<Output = ()> + Send;
fn next_action(&mut self) -> impl Future<Output = Action<Self::State>> + Send;
fn deliver_response<'a>(
&mut self,
response: Self::Response<'a>,
) -> impl Future<Output = ()> + Send;
}
pub async fn run_game<G>(game: &mut G, host: &str, port: usize) -> Result<()>
where
G: BaseGame,
{
let mut connection = Connection::new(host, port).await?;
connection
.send_message(BitBrokerMessage::initial_game_message())
.await
.unwrap();
let initial_message: BitBrokerMessage = connection.read_message().await?;
match initial_message.codes() {
(0x00, 0x11) => game.initialise(initial_message.body_proto()?).await,
_ => return Err(initial_message.into()),
}
loop {
let message: BitBrokerMessage = connection.read_message().await?;
match message.codes() {
(0x00, 0xFF) => return Ok(()),
(0x01, 0x00) => {
let action = game.next_action().await;
let has_response = action.has_response();
connection
.send_message(BitBrokerMessage::from(action))
.await?;
if has_response {
let response: BitBrokerMessage = connection.read_message().await?;
game.deliver_response(response.body().into()).await;
}
}
_ => return Err(initial_message.into()),
}
}
}