···11use chrono::{DateTime, Utc};
22-use events::GameEvent;
22+pub use events::GameEvent;
33+use matchbox_socket::PeerId;
34use powerups::PowerUpType;
44-use settings::GameSettings;
55-use std::{collections::HashMap, fmt::Debug, hash::Hash, time::Duration};
55+pub use settings::GameSettings;
66+use std::{collections::HashMap, fmt::Debug, hash::Hash, ops::Deref, sync::Arc, time::Duration};
77+use uuid::Uuid;
6879use tokio::{sync::RwLock, time::MissedTickBehavior};
810···1315mod state;
1416mod transport;
15171616-use location::LocationService;
1818+pub use location::{Location, LocationService};
1719use state::GameState;
1818-use transport::Transport;
2020+pub use transport::Transport;
19212022/// Type used to uniquely identify players in the game
2123pub trait PlayerId:
2224 Debug + Hash + Ord + Eq + PartialEq + Send + Sync + Sized + Copy + Clone
2325{
2426}
2727+2828+impl PlayerId for Uuid {}
2929+impl PlayerId for PeerId {}
25302631/// Convenence alias for UTC DT
2732pub type UtcDT = DateTime<Utc>;
···2934/// Struct representing an ongoing game, handles communication with
3035/// other clients via [Transport], gets location with [LocationService], and provides high-level methods for
3136/// taking actions in the game.
3232-struct Game<Id: PlayerId, L: LocationService, T: Transport<Id>> {
3737+pub struct Game<Id: PlayerId, L: LocationService, T: Transport<Id>> {
3338 state: RwLock<GameState<Id>>,
3434- transport: T,
3939+ transport: Arc<T>,
3540 location: L,
3641 interval: Duration,
3742}
···4045 pub fn new(
4146 my_id: Id,
4247 interval: Duration,
4343- random_seed: u64,
4448 initial_caught_state: HashMap<Id, bool>,
4549 settings: GameSettings,
4646- transport: T,
5050+ transport: Arc<T>,
4751 location: L,
4852 ) -> Self {
4949- let state = GameState::<Id>::new(settings, my_id, random_seed, initial_caught_state);
5353+ let state = GameState::<Id>::new(settings, my_id, initial_caught_state);
50545155 Self {
5256 transport,
···139143 let mut state = self.state.write().await;
140144141145 // Push to location history
142142- let location = self.location.get_loc();
143143- state.push_loc(location);
146146+ if let Some(location) = self.location.get_loc() {
147147+ state.push_loc(location);
148148+ }
144149145150 // Release Seekers?
146151 if !state.seekers_released() && state.should_release_seekers(now) {
···248253 struct MockLocation;
249254250255 impl LocationService for MockLocation {
251251- fn get_loc(&self) -> location::Location {
252252- location::Location {
256256+ fn get_loc(&self) -> Option<Location> {
257257+ Some(location::Location {
253258 lat: 0.0,
254259 long: 0.0,
255260 heading: None,
256256- }
261261+ })
257262 }
258263 }
259264···295300 let game = TestGame::new(
296301 id as u32,
297302 INTERVAL,
298298- 0,
299303 initial_caught_state.clone(),
300304 settings.clone(),
301301- transport,
305305+ Arc::new(transport),
302306 location,
303307 );
304308···365369366370 fn mk_settings() -> GameSettings {
367371 GameSettings {
372372+ random_seed: 0,
368373 hiding_time_seconds: 1,
369374 ping_start: PingStartCondition::Instant,
370375 ping_minutes_interval: 1,
+17
backend/src/game/settings.rs
···1717#[derive(Debug, Clone, Serialize, Deserialize)]
1818/// Settings for the game, host is the only person able to change these
1919pub struct GameSettings {
2020+ /// The random seed used for shared rng
2121+ pub random_seed: u64,
2022 /// The number of seconds to wait before seekers are allowed to go
2123 pub hiding_time_seconds: u32,
2224 /// Condition to wait for global pings to begin
···3941 Bernoulli::from_ratio(self.powerup_chance, 100).unwrap()
4042 }
4143}
4444+4545+impl Default for GameSettings {
4646+ fn default() -> Self {
4747+ Self {
4848+ random_seed: rand::random_range(0..=u64::MAX),
4949+ hiding_time_seconds: 60,
5050+ ping_start: PingStartCondition::Players(2),
5151+ ping_minutes_interval: 3,
5252+ powerup_start: PingStartCondition::Minutes(5),
5353+ powerup_chance: 25,
5454+ powerup_minutes_cooldown: 5,
5555+ powerup_locations: vec![],
5656+ }
5757+ }
5858+}