22
33use std:: { fmt:: Debug , marker:: PhantomData , sync:: Arc } ;
44
5+ use bones_matchmaker_proto:: { MATCH_ALPN , PLAY_ALPN } ;
56use ggrs:: { NetworkStats , P2PSession , PlayerHandle } ;
67use instant:: Duration ;
78use once_cell:: sync:: Lazy ;
@@ -12,15 +13,20 @@ use crate::prelude::*;
1213use self :: {
1314 debug:: { NetworkDebugMessage , NETWORK_DEBUG_CHANNEL } ,
1415 input:: { DenseInput , NetworkInputConfig , NetworkPlayerControl , NetworkPlayerControls } ,
16+ socket:: Socket ,
1517} ;
1618use crate :: input:: PlayerControls as PlayerControlsTrait ;
1719
18- pub mod certs;
1920pub mod debug;
2021pub mod input;
2122pub mod lan;
2223pub mod online;
2324pub mod proto;
25+ pub mod socket;
26+
27+ /// Runtime, needed to execute network related calls.
28+ pub static RUNTIME : Lazy < tokio:: runtime:: Runtime > =
29+ Lazy :: new ( || tokio:: runtime:: Runtime :: new ( ) . expect ( "unable to crate tokio runtime" ) ) ;
2430
2531/// Indicates if input from networking is confirmed, predicted, or if player is disconnected.
2632#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
@@ -45,7 +51,7 @@ impl From<ggrs::InputStatus> for NetworkInputStatus {
4551
4652/// Module prelude.
4753pub mod prelude {
48- pub use super :: { certs , debug:: prelude:: * , input, lan, online, proto, NetworkInfo } ;
54+ pub use super :: { debug:: prelude:: * , input, lan, online, proto, NetworkInfo , RUNTIME } ;
4955}
5056
5157/// Muliplier for framerate that will be used when playing an online match.
@@ -66,12 +72,8 @@ pub const NETWORK_MAX_PREDICTION_WINDOW_DEFAULT: usize = 7;
6672/// Amount of frames GGRS will delay local input.
6773pub const NETWORK_LOCAL_INPUT_DELAY_DEFAULT : usize = 2 ;
6874
69- // TODO: Remove this limitation on max players, a variety of types use this for static arrays,
70- // should either figure out how to make this a compile-time const value specified by game, or
71- // use dynamic arrays.
72- //
73- /// Max players in networked game
74- pub const MAX_PLAYERS : usize = 4 ;
75+ #[ doc( inline) ]
76+ pub use bones_matchmaker_proto:: MAX_PLAYERS ;
7577
7678/// Possible errors returned by network loop.
7779pub enum NetworkError {
@@ -92,40 +94,32 @@ impl<T: DenseInput + Debug> ggrs::Config for GgrsConfig<T> {
9294 type Address = usize ;
9395}
9496
95- /// The network endpoint used for all QUIC network communications.
96- pub static NETWORK_ENDPOINT : Lazy < quinn:: Endpoint > = Lazy :: new ( || {
97- // Generate certificate
98- let ( cert, key) = certs:: generate_self_signed_cert ( ) . unwrap ( ) ;
99-
100- let mut transport_config = quinn:: TransportConfig :: default ( ) ;
101- transport_config. keep_alive_interval ( Some ( std:: time:: Duration :: from_secs ( 5 ) ) ) ;
102-
103- let mut server_config = quinn:: ServerConfig :: with_single_cert ( [ cert] . to_vec ( ) , key) . unwrap ( ) ;
104- server_config. transport = Arc :: new ( transport_config) ;
105-
106- // Open Socket and create endpoint
107- let port = THREAD_RNG . with ( |rng| rng. u16 ( 10000 ..=11000 ) ) ;
108- info ! ( port, "Started network endpoint" ) ;
109- let socket = std:: net:: UdpSocket :: bind ( ( "0.0.0.0" , port) ) . unwrap ( ) ;
110-
111- let client_config = rustls:: ClientConfig :: builder ( )
112- . with_safe_defaults ( )
113- . with_custom_certificate_verifier ( certs:: SkipServerVerification :: new ( ) )
114- . with_no_client_auth ( ) ;
115- let client_config = quinn:: ClientConfig :: new ( Arc :: new ( client_config) ) ;
116-
117- let mut endpoint = quinn:: Endpoint :: new (
118- quinn:: EndpointConfig :: default ( ) ,
119- Some ( server_config) ,
120- socket,
121- Arc :: new ( quinn_runtime_bevy:: BevyIoTaskPoolExecutor ) ,
122- )
123- . unwrap ( ) ;
124-
125- endpoint. set_default_client_config ( client_config) ;
126-
127- endpoint
128- } ) ;
97+ /// The network endpoint used for all network communications.
98+ static NETWORK_ENDPOINT : tokio:: sync:: OnceCell < iroh_net:: MagicEndpoint > =
99+ tokio:: sync:: OnceCell :: const_new ( ) ;
100+
101+ /// Get the network endpoint used for all communications.
102+ pub async fn get_network_endpoint ( ) -> & ' static iroh_net:: MagicEndpoint {
103+ NETWORK_ENDPOINT
104+ . get_or_init ( || async move {
105+ let secret_key = iroh_net:: key:: SecretKey :: generate ( ) ;
106+ iroh_net:: MagicEndpoint :: builder ( )
107+ . alpns ( vec ! [ MATCH_ALPN . to_vec( ) , PLAY_ALPN . to_vec( ) ] )
108+ . discovery ( Box :: new (
109+ iroh_net:: discovery:: ConcurrentDiscovery :: from_services ( vec ! [
110+ Box :: new( iroh_net:: discovery:: dns:: DnsDiscovery :: n0_dns( ) ) ,
111+ Box :: new( iroh_net:: discovery:: pkarr_publish:: PkarrPublisher :: n0_dns(
112+ secret_key. clone( ) ,
113+ ) ) ,
114+ ] ) ,
115+ ) )
116+ . secret_key ( secret_key)
117+ . bind ( 0 )
118+ . await
119+ . unwrap ( )
120+ } )
121+ . await
122+ }
129123
130124/// Resource containing the [`NetworkSocket`] implementation while there is a connection to a
131125/// network game.
@@ -135,17 +129,6 @@ pub static NETWORK_ENDPOINT: Lazy<quinn::Endpoint> = Lazy::new(|| {
135129#[ schema( no_default) ]
136130pub struct NetworkMatchSocket ( Arc < dyn NetworkSocket > ) ;
137131
138- /// A type-erased [`ggrs::NonBlockingSocket`]
139- /// implementation.
140- #[ derive( Deref , DerefMut ) ]
141- pub struct BoxedNonBlockingSocket ( Box < dyn GgrsSocket > ) ;
142-
143- impl Clone for BoxedNonBlockingSocket {
144- fn clone ( & self ) -> Self {
145- self . ggrs_socket ( )
146- }
147- }
148-
149132/// Wraps [`ggrs::Message`] with included `match_id`, used to determine if message received
150133/// from current match.
151134#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -160,23 +143,13 @@ pub struct GameMessage {
160143pub trait GgrsSocket : NetworkSocket + ggrs:: NonBlockingSocket < usize > { }
161144impl < T > GgrsSocket for T where T : NetworkSocket + ggrs:: NonBlockingSocket < usize > { }
162145
163- impl ggrs:: NonBlockingSocket < usize > for BoxedNonBlockingSocket {
164- fn send_to ( & mut self , msg : & ggrs:: Message , addr : & usize ) {
165- self . 0 . send_to ( msg, addr)
166- }
167-
168- fn receive_all_messages ( & mut self ) -> Vec < ( usize , ggrs:: Message ) > {
169- self . 0 . receive_all_messages ( )
170- }
171- }
172-
173146/// Trait that must be implemented by socket connections establish by matchmakers.
174147///
175148/// The [`NetworkMatchSocket`] resource will contain an instance of this trait and will be used by
176149/// the game to send network messages after a match has been established.
177150pub trait NetworkSocket : Sync + Send {
178151 /// Get a GGRS socket from this network socket.
179- fn ggrs_socket ( & self ) -> BoxedNonBlockingSocket ;
152+ fn ggrs_socket ( & self ) -> Socket ;
180153 /// Send a reliable message to the given [`SocketTarget`].
181154 fn send_reliable ( & self , target : SocketTarget , message : & [ u8 ] ) ;
182155 /// Receive reliable messages from other players. The `usize` is the index of the player that
@@ -216,7 +189,7 @@ pub struct NetworkInfo {
216189 pub last_confirmed_frame : i32 ,
217190
218191 /// Socket
219- pub socket : BoxedNonBlockingSocket ,
192+ pub socket : Socket ,
220193}
221194
222195/// [`SessionRunner`] implementation that uses [`ggrs`] for network play.
@@ -251,7 +224,7 @@ pub struct GgrsSessionRunner<'a, InputTypes: NetworkInputConfig<'a>> {
251224 pub input_collector : InputTypes :: InputCollector ,
252225
253226 /// Store copy of socket to be able to restart session runner with existing socket.
254- socket : BoxedNonBlockingSocket ,
227+ socket : Socket ,
255228
256229 /// Local input delay ggrs session was initialized with
257230 local_input_delay : usize ,
@@ -261,7 +234,7 @@ pub struct GgrsSessionRunner<'a, InputTypes: NetworkInputConfig<'a>> {
261234#[ derive( Clone ) ]
262235pub struct GgrsSessionRunnerInfo {
263236 /// The socket that will be converted into GGRS socket implementation.
264- pub socket : BoxedNonBlockingSocket ,
237+ pub socket : Socket ,
265238 /// The list of local players.
266239 pub player_is_local : [ bool ; MAX_PLAYERS ] ,
267240 /// the player count.
@@ -282,12 +255,12 @@ pub struct GgrsSessionRunnerInfo {
282255impl GgrsSessionRunnerInfo {
283256 /// See [`GgrsSessionRunnerInfo`] fields for info on arguments.
284257 pub fn new (
285- socket : BoxedNonBlockingSocket ,
258+ socket : Socket ,
286259 max_prediction_window : Option < usize > ,
287260 local_input_delay : Option < usize > ,
288261 ) -> Self {
289- let player_is_local = socket. 0 . player_is_local ( ) ;
290- let player_count = socket. 0 . player_count ( ) ;
262+ let player_is_local = socket. player_is_local ( ) ;
263+ let player_count = socket. player_count ( ) ;
291264 Self {
292265 socket,
293266 player_is_local,
@@ -591,7 +564,7 @@ where
591564
592565 // Increment match id so messages from previous match that are still in flight
593566 // will be filtered out.
594- self . socket . 0 . increment_match_id ( ) ;
567+ self . socket . increment_match_id ( ) ;
595568
596569 let runner_info = GgrsSessionRunnerInfo {
597570 socket : self . socket . clone ( ) ,
0 commit comments