How to do it...

  1. In the src/bin folder, create a file called returning.rs.
  2. Add the following code and run it with cargo run —bin returning:
1   extern crate futures;
2   
3   use futures::executor::block_on;
4   use futures::future::{join_all, Future, FutureResult, ok};
5   use futures::prelude::*;
6   
7   #[derive(Clone, Copy, Debug, PartialEq)]
8   enum PlayerStatus {
9     Loading,
10    Default,
11    Jumping,
12  }
13  
14  #[derive(Clone, Copy, Debug)]
15  struct Player {
16    name: &'static str,
17    status: PlayerStatus,
18    score: u32,
19    ticks: usize,
20  }
  1. Now comes the implementations for the structs:
22  impl Player {
23    fn new(name: &'static str) -> Self {
24      let mut ticks = 1;
25      // Give Bob more ticks explicitly
26      if name == "Bob" {
27        ticks = 5;
28      }
29  
30      Player {
31        name: name,
32        status: PlayerStatus::Loading,
33        score: 0,
34        ticks: ticks,
35      }
36    }
37  
38    fn set_status(&mut self, status: PlayerStatus) ->  
FutureResult<&mut Self, Never> { 39 self.status = status; 40 ok(self) 41 } 42 43 fn can_add_points(&mut self) -> bool { 44 if self.status == PlayerStatus::Default { 45 return true; 46 } 47 48 println!("We couldn't add any points for {}!", self.name); 49 return false; 50 } 51 52 fn add_points(&mut self, points: u32) -> Async<&mut Self> { 53 if !self.can_add_points() { 54 Async::Ready(self) 55 } else { 56 let new_score = self.score + points; 57 // Here we would send the new score to a remote server 58 // but for now we will manaully increment the player's
score. 59 60 self.score = new_score; 61 62 Async::Ready(self) 63 } 64 } 65 } 66 67 impl Future for Player { 68 type Item = Player; 69 type Error = (); 70 71 fn poll(&mut self, cx: &mut task::Context) ->
Poll<Self::Item, Self::Error> { 72 // Presuming we fetch our player's score from a 73 // server upon initial load. 74 // After we perform the fetch send the Result value. 75 76 println!("Player {} has been poll'ed!", self.name); 77 78 if self.ticks == 0 { 79 self.status = PlayerStatus::Default; 80 Ok(Async::Ready(*self)) 81 } else { 82 self.ticks -= 1; 83 cx.waker().wake(); 84 Ok(Async::Pending) 85 } 86 } 87 }
  1. Next, we'll want to add our helper functions and our Async function for adding points to our players:
89  fn async_add_points(player: &mut Player,
90            points: u32)
91            -> Box<Future + Send> {
92    // Presuming that player.add_points() will send the points to a
93    // database/server over a network and returns an updated
94    // player score from the server/database.
95    let _ = player.add_points(points);
96  
97    // Additionally, we may want to add logging mechanisms,
98    // friend notifications, etc. here.
99  
100   return Box::new(ok(*player));
101 }
102 
103 fn display_scoreboard(players: Vec<&Player>) {
104   for player in players {
105     println!("{}'s Score: {}", player.name, player.score);
106   }
107 }
  1. And finally, the actual usage:
109 fn main() {
110   let mut player1 = Player::new("Bob");
111   let mut player2 = Player::new("Alice");
112 
113   let tasks = join_all(vec![player1, player2]);
114 
115   let f = join_all(vec![
116     async_add_points(&mut player1, 5),
117     async_add_points(&mut player2, 2),
118   ])
119     .then(|x| {
120       println!("First batch of adding points is done.");
121       x
122     });
123 
124   block_on(f).unwrap();
125 
126   let players = block_on(tasks).unwrap();
127   player1 = players[0];
128   player2 = players[1];
129 
130   println!("Scores should be zero since no players were  
loaded"); 131 display_scoreboard(vec![&player1, &player2]); 132 133 // In our minigame, a player cannot score if they are
currently 134 // in the air or "jumping." 135 // Let's make one of our players' status set to the jumping
status. 136 137 let f =
player2.set_status(PlayerStatus::Jumping).and_then(move |mut
new_player2| { 138 async_add_points(&mut player1, 10) 139 .and_then(move |_| { 140 println!("Finished trying to give Player 1 points."); 141 async_add_points(&mut new_player2, 2) 142 }) 143 .then(move |new_player2| { 144 println!("Finished trying to give Player 2 points."); 145 println!("Player 1 (Bob) should have a score of 10 and
Player 2 (Alice) should 146 have a score of 0"); 147 148 // unwrap is used here to since 149 display_scoreboard(vec![&player1,
&new_player2.unwrap()]); 150 new_player2 151 }) 152 }); 153 154 block_on(f).unwrap(); 155 156 println!("All done!"); 157 }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.178.181