use crate::battle::{Battle, BattleController, BattleRules, EventCallback};
use crate::error::WeaselResult;
use crate::event::{
EventProcessor, EventPrototype, EventReceiver, MultiClientSink, MultiClientSinkHandle,
MultiClientSinkHandleMut, ServerSink, VersionedEventWrapper,
};
use crate::player::PlayerId;
pub struct Client<R: BattleRules> {
battle: Battle<R>,
server_sink: Box<dyn ServerSink<R> + Send>,
client_sinks: MultiClientSink<R>,
player: Option<PlayerId>,
}
impl<R: BattleRules + 'static> Client<R> {
pub fn builder(
battle: Battle<R>,
server_sink: Box<dyn ServerSink<R> + Send>,
) -> ClientBuilder<R> {
ClientBuilder {
battle,
server_sink,
player: None,
}
}
pub fn authentication(&self) -> bool {
self.player.is_some()
}
pub fn player(&self) -> &Option<PlayerId> {
&self.player
}
pub fn server_sink(&self) -> &(dyn ServerSink<R> + Send) {
&*self.server_sink
}
pub fn set_server_sink(&mut self, sink: Box<dyn ServerSink<R> + Send>) {
self.server_sink.on_disconnect();
self.server_sink = sink;
}
pub fn client_sinks(&self) -> MultiClientSinkHandle<'_, R> {
MultiClientSinkHandle::new(&self.client_sinks)
}
pub fn client_sinks_mut(&mut self) -> MultiClientSinkHandleMut<'_, R> {
MultiClientSinkHandleMut::new(&mut self.client_sinks, &self.battle)
}
}
impl<R: BattleRules> BattleController<R> for Client<R> {
fn battle(&self) -> &Battle<R> {
&self.battle
}
fn event_callback(&self) -> &Option<EventCallback<R>> {
&self.battle.event_callback
}
fn set_event_callback(&mut self, callback: Option<EventCallback<R>>) {
self.battle.event_callback = callback;
}
}
impl<R: BattleRules + 'static> EventProcessor<R> for Client<R> {
type ProcessOutput = WeaselResult<(), R>;
fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput {
self.battle.verify_prototype(&event)?;
let event = event.client_prototype(self.battle().rules().version().clone(), self.player);
self.server_sink.send(&event)
}
}
impl<R: BattleRules + 'static> EventReceiver<R> for Client<R> {
fn receive(&mut self, event: VersionedEventWrapper<R>) -> WeaselResult<(), R> {
self.battle.verify_wrapper(&event)?;
self.battle.apply(&event.wrapper(), &mut None);
self.client_sinks.send_all(&event);
Ok(())
}
}
pub struct ClientBuilder<R: BattleRules> {
battle: Battle<R>,
server_sink: Box<dyn ServerSink<R> + Send>,
player: Option<PlayerId>,
}
impl<R: BattleRules> ClientBuilder<R> {
pub fn enable_authentication(mut self, player: PlayerId) -> Self {
self.player = Some(player);
self
}
pub fn build(self) -> Client<R> {
Client {
battle: self.battle,
server_sink: self.server_sink,
client_sinks: MultiClientSink::new(),
player: self.player,
}
}
}