| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use crate::game::{Game, PlayerState}; |
| use anyhow::Context; |
| use fidl_fuchsia_game_tennis as fidl_tennis; |
| use fuchsia_async::{self as fasync, DurationExt}; |
| use fuchsia_syslog::{fx_log_err, fx_log_info}; |
| use fuchsia_zircon::DurationNum; |
| use futures::prelude::*; |
| use parking_lot::Mutex; |
| use std::sync::Arc; |
| |
| #[derive(Clone)] |
| pub struct TennisService(Arc<Mutex<Game>>); |
| |
| impl TennisService { |
| pub fn new() -> TennisService { |
| TennisService(Arc::new(Mutex::new(Game::new()))) |
| } |
| |
| pub fn bind(&self, mut stream: fidl_tennis::TennisServiceRequestStream) { |
| let self_clone = self.clone(); |
| fuchsia_async::Task::spawn( |
| async move { |
| while let Some(msg) = stream |
| .try_next() |
| .await |
| .context("error reading value from tennis service request stream")? |
| { |
| match msg { |
| fidl_tennis::TennisServiceRequest::GetState { responder, .. } => { |
| let TennisService(game_arc) = &self_clone; |
| responder |
| .send(&mut game_arc.lock().state()) |
| .context("error sending GetState response")?; |
| } |
| fidl_tennis::TennisServiceRequest::RegisterPaddle { |
| player_name, |
| paddle, |
| .. |
| } => { |
| fx_log_info!("new paddle registered: {}", player_name); |
| self_clone.register_paddle(player_name, paddle); |
| } |
| } |
| } |
| Ok(()) |
| } |
| .unwrap_or_else(|e: anyhow::Error| fx_log_err!("{:?}", e)), |
| ) |
| .detach(); |
| } |
| |
| pub fn register_paddle( |
| &self, |
| player_name: String, |
| paddle: fidl::endpoints::ClientEnd<fidl_fuchsia_game_tennis::PaddleMarker>, |
| ) { |
| let TennisService(game_arc) = self.clone(); |
| let mut game = game_arc.lock(); |
| let paddle_proxy = paddle.into_proxy().unwrap(); |
| let mut stream = paddle_proxy.take_event_stream(); |
| let player_state = game.register_new_paddle(player_name.clone(), paddle_proxy); |
| fasync::Task::spawn( |
| async move { |
| while let Some(event) = stream |
| .try_next() |
| .await |
| .context("error reading value from paddle event stream")? |
| { |
| let state = match event { |
| fidl_tennis::PaddleEvent::Up { .. } => PlayerState::Up, |
| fidl_tennis::PaddleEvent::Down { .. } => PlayerState::Down, |
| fidl_tennis::PaddleEvent::Stop { .. } => PlayerState::Stop, |
| }; |
| *player_state.lock() = state; |
| } |
| *player_state.lock() = PlayerState::Disconnected; |
| Ok(()) |
| } |
| .unwrap_or_else(|e: anyhow::Error| fx_log_err!("{:?}", e)), |
| ) |
| .detach(); |
| if game.players_ready() { |
| fx_log_info!("game is beginning"); |
| let game_arc = game_arc.clone(); |
| fasync::Task::spawn(async move { |
| loop { |
| game_arc.lock().step(); |
| let time_step: i64 = (100.0 * game_arc.lock().time_scale_factor()) as i64; |
| fuchsia_async::Timer::new(time_step.millis().after_now()).await; |
| if !game_arc.lock().players_ready() { |
| fx_log_info!("someone disconnected!"); |
| return; |
| } |
| } |
| }) |
| .detach(); |
| } |
| } |
| } |