mod.rs (3909B)
1 use std::{ 2 collections::VecDeque, 3 sync::mpsc::{Receiver, Sender}, 4 time::{Duration, Instant, SystemTime}, 5 }; 6 7 use crate::render::Camera; 8 use common::game::{Action, ActionKind, Player, Response, book::FloorBook, state::GameState}; 9 use macroquad::prelude::*; 10 use serde::{Deserialize, Serialize}; 11 use uuid::Uuid; 12 13 mod run; 14 mod state; 15 16 const CONFY_APP_NAME: &str = "library-game"; 17 const CONFY_CONFIG_NAME: &str = "config"; 18 19 #[derive(Debug)] 20 pub(crate) struct ClientState { 21 mode: ViewMode, 22 camera: Camera, 23 game: GameState, 24 old_game: GameState, 25 local_player_id: Option<Uuid>, 26 sequence_number: u32, 27 unresponded_actions: VecDeque<Action>, 28 interpolation_basis: SystemTime, 29 debug_view: bool, 30 t0: Instant, 31 t1: Instant, 32 dt: Duration, 33 tx: Option<Sender<Action>>, 34 rx: Option<Receiver<Response>>, 35 config: Config, 36 menu_error: String, 37 first_frame: bool, 38 selected_book: usize, 39 } 40 41 impl Default for ClientState { 42 fn default() -> Self { 43 Self { 44 mode: ViewMode::default(), 45 camera: Camera::default(), 46 game: GameState::default(), 47 old_game: GameState::default(), 48 local_player_id: None, 49 sequence_number: 0, 50 unresponded_actions: VecDeque::new(), 51 interpolation_basis: SystemTime::now(), 52 debug_view: cfg!(debug_assertions), 53 t0: Instant::now(), 54 t1: Instant::now(), 55 dt: Duration::ZERO, 56 tx: None, 57 rx: None, 58 config: confy::load(CONFY_APP_NAME, Some(CONFY_CONFIG_NAME)).unwrap_or_default(), 59 menu_error: String::new(), 60 first_frame: true, 61 selected_book: 0, 62 } 63 } 64 } 65 66 pub(crate) fn handle_movement_input(local_player: &Player, dt: &Duration) -> Option<ActionKind> { 67 let velocity_x = if is_key_down(KeyCode::A) || is_key_down(KeyCode::Left) { 68 -GameState::MAX_PLAYER_SPEED_PX_S 69 } else if is_key_down(KeyCode::D) || is_key_down(KeyCode::Right) { 70 GameState::MAX_PLAYER_SPEED_PX_S 71 } else { 72 0. 73 }; 74 let velocity_y = if is_key_down(KeyCode::W) || is_key_down(KeyCode::Up) { 75 -GameState::MAX_PLAYER_SPEED_PX_S 76 } else if is_key_down(KeyCode::S) || is_key_down(KeyCode::Down) { 77 GameState::MAX_PLAYER_SPEED_PX_S 78 } else { 79 0. 80 }; 81 if velocity_x != 0. || velocity_y != 0. { 82 Some(ActionKind::Move { 83 new_position: local_player.position() 84 + Vec2::new(velocity_x, velocity_y) * dt.as_secs_f32(), 85 }) 86 } else { 87 None 88 } 89 } 90 91 pub(crate) fn handle_pick_up_book_input( 92 local_player: &Player, 93 floor_books: &[FloorBook], 94 ) -> Option<ActionKind> { 95 if is_key_pressed(KeyCode::Space) { 96 let local_player_collider = local_player 97 .collider() 98 .rect() 99 .offset(local_player.position()); 100 if let Some(floor_book) = floor_books.iter().find(|fb| { 101 fb.collider() 102 .rect() 103 .offset(fb.position()) 104 .overlaps(&local_player_collider) 105 }) { 106 return Some(ActionKind::PickUpBook { 107 book_id: floor_book.id(), 108 }); 109 } 110 } 111 None 112 } 113 114 pub(crate) fn handle_drop_book_input( 115 local_player: &Player, 116 selected_book_index: usize, 117 ) -> Option<ActionKind> { 118 if is_key_pressed(KeyCode::Q) 119 && let Some(book_id) = local_player.books().get(selected_book_index) 120 { 121 Some(ActionKind::DropBook { book_id: *book_id }) 122 } else { 123 None 124 } 125 } 126 127 #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] 128 struct Config { 129 player_name: String, 130 server: String, 131 } 132 133 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] 134 pub(crate) enum ViewMode { 135 #[default] 136 Menu, 137 Game, 138 }