library

Online co-op book organization video game
git clone https://git.bradleygannon.com/library.git
Log | Files | Refs

state.rs (2709B)


      1 use std::time::{Instant, SystemTime};
      2 
      3 use common::game::{Action, ActionKind, Response, ResponseKind, state::GameState};
      4 use structdiff::StructDiff;
      5 
      6 use crate::game::{ClientState, ViewMode};
      7 
      8 impl ClientState {
      9     pub(crate) fn view_mode(&self) -> ViewMode {
     10         self.mode
     11     }
     12     pub(crate) fn tick(&mut self) {
     13         self.t0 = self.t1;
     14         self.t1 = Instant::now();
     15         self.dt = self.t1.duration_since(self.t0);
     16     }
     17     pub(crate) fn advance_game_state(&mut self) {
     18         self.old_game = self.game.clone();
     19     }
     20     pub(crate) fn send_action(&mut self, action: &Action) {
     21         if let Some(ref mut tx) = self.tx
     22             && tx.send(action.clone()).is_err()
     23         {
     24             return;
     25         }
     26         self.unresponded_actions.push_back(action.clone());
     27         self.sequence_number = self.sequence_number.wrapping_add(1);
     28     }
     29     pub(crate) fn handle_response(&mut self, response: &Response) {
     30         match response.kind() {
     31             ResponseKind::SetId { id } => {
     32                 let action = Action::new(
     33                     self.sequence_number,
     34                     id,
     35                     ActionKind::Join {
     36                         name: self.config.player_name.clone(),
     37                     },
     38                 );
     39                 self.send_action(&action);
     40                 self.local_player_id = Some(id);
     41             }
     42             ResponseKind::UpdateGameState { diffs } => {
     43                 self.game.set_timestamp(response.timestamp());
     44                 self.game.apply_mut(diffs);
     45             }
     46             ResponseKind::ReplaceGameState { new_game_state } => self.game = new_game_state,
     47         };
     48     }
     49     pub(crate) fn reconcile(&mut self, latest_sequence_number: u32) {
     50         // Server reconciliation: drop any unresponded actions whose sequence numbers are less than
     51         // the number provided
     52         if let Some(new_front_index) = self
     53             .unresponded_actions
     54             .iter()
     55             .position(|ua: &Action| ua.sequence_number() >= latest_sequence_number)
     56         {
     57             for _ in 0..=new_front_index {
     58                 self.unresponded_actions.pop_front();
     59             }
     60         }
     61     }
     62     pub(crate) fn predict(&mut self) {
     63         // Client prediction: apply all unresponded actions to the game state
     64         self.interpolation_basis = SystemTime::now();
     65         for unresponded_action in self.unresponded_actions.iter() {
     66             self.game.apply_action(unresponded_action);
     67         }
     68     }
     69     pub(crate) fn interpolate(&self) -> GameState {
     70         GameState::interpolate(
     71             &self.old_game,
     72             &self.game,
     73             self.interpolation_basis,
     74             self.local_player_id,
     75         )
     76     }
     77 }