use std::net::SocketAddr; use avian2d::PhysicsPlugins; use bevy::{input::common_conditions::input_pressed, prelude::*}; use crate::net::prelude::*; use super::{ net::{handle_deleted_peer, handle_incoming_packets, handle_new_peer}, runtime::{move_camera, move_player, quit, zoom_camera}, seed::Seed, setup::{ check_for_seed, setup_balls, setup_camera, setup_from_seed, setup_player, setup_walls, }, state::AppState, ui::{ setup_peer_ui, setup_potential_peer_ui, setup_seed_ui, update_peer_ui, update_peer_ui_timings, update_potential_peer_ui, update_seed_ui, }, }; #[derive(Debug, Clone, Copy)] pub enum DataSource { Address(SocketAddr), Seed(Seed), None, } impl DataSource { pub fn try_from_options(address: Option, seed: Option) -> Option { match (address, seed) { (None, None) => Some(DataSource::None), (None, Some(seed)) => Some(DataSource::Seed(seed)), (Some(address), None) => Some(DataSource::Address(address)), (Some(_), Some(_)) => None, } } fn try_to_address(&self) -> Option { match self { DataSource::Address(address) => Some(*address), _ => None, } } } pub struct GamePlugin { source: DataSource, port: u16, } impl GamePlugin { pub fn new(source: DataSource, port: u16) -> Self { Self { source, port } } } impl Plugin for GamePlugin { fn build(&self, app: &mut App) { app.add_plugins(( NetIOPlugin::maybe_peer(self.port, self.source.try_to_address()), distribution_plugin::, PhysicsPlugins::default().with_length_unit(50.0), )) .init_state::() .add_systems( Startup, ( setup_camera, setup_seed_ui, setup_peer_ui, setup_potential_peer_ui, ), ) .add_systems( OnEnter(AppState::InGame), (setup_from_seed, (setup_player, setup_balls, setup_walls)).chain(), ) .add_systems( FixedUpdate, ( check_for_seed.run_if(in_state(AppState::Loading)), handle_incoming_packets, ), ) .add_systems( Update, ( ((move_player, move_camera).chain(), zoom_camera) .run_if(in_state(AppState::InGame)), update_seed_ui, ( update_peer_ui, update_peer_ui_timings, update_potential_peer_ui, ), quit.run_if(input_pressed(KeyCode::KeyQ)), ), ) .add_observer(handle_new_peer) .add_observer(handle_deleted_peer); match self.source { DataSource::Address(peer) => { info!("Will retrieve seed from peer => {peer}"); } DataSource::Seed(seed) => { app.world_mut().spawn(seed); } DataSource::None => { app.world_mut().spawn(Seed::random()); } }; } }